illumio-pylo 0.2.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. illumio_pylo/API/APIConnector.py +1308 -0
  2. illumio_pylo/API/AuditLog.py +42 -0
  3. illumio_pylo/API/ClusterHealth.py +136 -0
  4. illumio_pylo/API/CredentialsManager.py +286 -0
  5. illumio_pylo/API/Explorer.py +1077 -0
  6. illumio_pylo/API/JsonPayloadTypes.py +240 -0
  7. illumio_pylo/API/RuleSearchQuery.py +128 -0
  8. illumio_pylo/API/__init__.py +0 -0
  9. illumio_pylo/AgentStore.py +139 -0
  10. illumio_pylo/Exception.py +44 -0
  11. illumio_pylo/Helpers/__init__.py +3 -0
  12. illumio_pylo/Helpers/exports.py +508 -0
  13. illumio_pylo/Helpers/functions.py +166 -0
  14. illumio_pylo/IPList.py +135 -0
  15. illumio_pylo/IPMap.py +285 -0
  16. illumio_pylo/Label.py +25 -0
  17. illumio_pylo/LabelCommon.py +48 -0
  18. illumio_pylo/LabelGroup.py +68 -0
  19. illumio_pylo/LabelStore.py +403 -0
  20. illumio_pylo/LabeledObject.py +25 -0
  21. illumio_pylo/Organization.py +258 -0
  22. illumio_pylo/Query.py +331 -0
  23. illumio_pylo/ReferenceTracker.py +41 -0
  24. illumio_pylo/Rule.py +671 -0
  25. illumio_pylo/Ruleset.py +306 -0
  26. illumio_pylo/RulesetStore.py +101 -0
  27. illumio_pylo/SecurityPrincipal.py +62 -0
  28. illumio_pylo/Service.py +256 -0
  29. illumio_pylo/SoftwareVersion.py +125 -0
  30. illumio_pylo/VirtualService.py +17 -0
  31. illumio_pylo/VirtualServiceStore.py +75 -0
  32. illumio_pylo/Workload.py +506 -0
  33. illumio_pylo/WorkloadStore.py +289 -0
  34. illumio_pylo/__init__.py +82 -0
  35. illumio_pylo/cli/NativeParsers.py +96 -0
  36. illumio_pylo/cli/__init__.py +134 -0
  37. illumio_pylo/cli/__main__.py +10 -0
  38. illumio_pylo/cli/commands/__init__.py +32 -0
  39. illumio_pylo/cli/commands/credential_manager.py +168 -0
  40. illumio_pylo/cli/commands/iplist_import_from_file.py +185 -0
  41. illumio_pylo/cli/commands/misc.py +7 -0
  42. illumio_pylo/cli/commands/ruleset_export.py +129 -0
  43. illumio_pylo/cli/commands/update_pce_objects_cache.py +44 -0
  44. illumio_pylo/cli/commands/ven_duplicate_remover.py +366 -0
  45. illumio_pylo/cli/commands/ven_idle_to_visibility.py +287 -0
  46. illumio_pylo/cli/commands/ven_upgrader.py +226 -0
  47. illumio_pylo/cli/commands/workload_export.py +251 -0
  48. illumio_pylo/cli/commands/workload_import.py +423 -0
  49. illumio_pylo/cli/commands/workload_relabeler.py +510 -0
  50. illumio_pylo/cli/commands/workload_reset_names_to_null.py +83 -0
  51. illumio_pylo/cli/commands/workload_used_in_rule_finder.py +80 -0
  52. illumio_pylo/docs/Doxygen +1757 -0
  53. illumio_pylo/tmp.py +104 -0
  54. illumio_pylo/utilities/__init__.py +0 -0
  55. illumio_pylo/utilities/cli.py +10 -0
  56. illumio_pylo/utilities/credentials.example.json +20 -0
  57. illumio_pylo/utilities/explorer_report_exporter.py +86 -0
  58. illumio_pylo/utilities/health_monitoring.py +102 -0
  59. illumio_pylo/utilities/iplist_analyzer.py +148 -0
  60. illumio_pylo/utilities/iplists_stats_duplicates_unused_finder.py +75 -0
  61. illumio_pylo/utilities/resources/iplists-import-example.csv +3 -0
  62. illumio_pylo/utilities/resources/iplists-import-example.xlsx +0 -0
  63. illumio_pylo/utilities/resources/workload-exporter-filter-example.csv +3 -0
  64. illumio_pylo/utilities/resources/workloads-import-example.csv +2 -0
  65. illumio_pylo/utilities/resources/workloads-import-example.xlsx +0 -0
  66. illumio_pylo/utilities/ven_compatibility_report_export.py +240 -0
  67. illumio_pylo/utilities/ven_idle_to_illumination.py +344 -0
  68. illumio_pylo/utilities/ven_reassign_pce.py +183 -0
  69. illumio_pylo-0.2.5.dist-info/LICENSE +176 -0
  70. illumio_pylo-0.2.5.dist-info/METADATA +197 -0
  71. illumio_pylo-0.2.5.dist-info/RECORD +73 -0
  72. illumio_pylo-0.2.5.dist-info/WHEEL +5 -0
  73. illumio_pylo-0.2.5.dist-info/top_level.txt +1 -0
@@ -0,0 +1,508 @@
1
+ from typing import Dict, Any, List, Optional, TypedDict, NotRequired
2
+
3
+ try:
4
+ import xlsxwriter
5
+ except ImportError:
6
+ import xlsxwriter
7
+
8
+ try:
9
+ import openpyxl
10
+ except ImportError:
11
+ import openpyxl
12
+
13
+ import csv
14
+ import illumio_pylo as pylo
15
+ import os
16
+
17
+
18
+ class ExcelHeader(TypedDict):
19
+ name: str
20
+ nice_name: NotRequired[str]
21
+ max_width: NotRequired[int]
22
+ wrap_text: NotRequired[bool]
23
+
24
+
25
+ class ArrayToExport:
26
+ def __init__(self, headers):
27
+ self._headers = headers
28
+ self._columns_count = len(headers)
29
+ self._lines = []
30
+
31
+ self._headers_name_to_index = {}
32
+ self._headers_index_to_name = []
33
+ index = 0
34
+ for header_name in headers:
35
+ self._headers_name_to_index[header_name] = index
36
+ self._headers_index_to_name.append(header_name)
37
+ index += 1
38
+
39
+ def columns_count(self):
40
+ return len(self._headers)
41
+
42
+ def lines_count(self):
43
+ return len(self._lines)
44
+
45
+ def add_line_from_object(self, record):
46
+ new_line = []
47
+ for header in self._headers:
48
+ new_line.append(record.get(header))
49
+
50
+ self._lines.append(new_line)
51
+
52
+ def add_line_from_list_of_objects(self, list_of_objects):
53
+ for record in list_of_objects:
54
+ self.add_line_from_object(record)
55
+
56
+ def add_line_from_list(self, line: list):
57
+ if len(line) != self._columns_count:
58
+ raise pylo.PyloEx("line length ({}) does not match the number of columns ({})".format(len(line), self._columns_count))
59
+ self._lines.append(line)
60
+
61
+ def write_to_csv(self, filename, delimiter=',', multivalues_cell_delimiter=' '):
62
+ with open(filename, 'w', newline='') as csv_file:
63
+ filewriter = csv.writer(csv_file, delimiter=delimiter, quotechar='"', quoting=csv.QUOTE_ALL)
64
+ filewriter.writerow(self._headers)
65
+ for line in self._lines:
66
+ new_line = []
67
+ for item in line:
68
+ if type(item) is list:
69
+ new_line.append(pylo.string_list_to_text(item, multivalues_cell_delimiter))
70
+ else:
71
+ new_line.append(item)
72
+ filewriter.writerow(new_line)
73
+
74
+ def write_to_excel(self, filename, worksheet_name='worksheet1', multivalues_cell_delimiter=' '):
75
+ xls_workbook = xlsxwriter.Workbook(filename)
76
+ cell_format = xls_workbook.add_format()
77
+ cell_format.set_text_wrap()
78
+ cell_format.set_valign('vcenter')
79
+ xls_worksheet = xls_workbook.add_worksheet(worksheet_name)
80
+ xls_headers = []
81
+ xls_data = []
82
+ header_index = 0
83
+ for header in self._headers:
84
+ xls_headers.append({'header': header, 'format': cell_format})
85
+ header_index += 1
86
+
87
+ # Building data array
88
+ for line in self._lines:
89
+ new_line = []
90
+ for item in line:
91
+ if type(item) is list:
92
+ new_line.append(pylo.string_list_to_text(item, multivalues_cell_delimiter))
93
+ else:
94
+ new_line.append(item)
95
+ xls_data.append(new_line)
96
+
97
+ xls_table = xls_worksheet.add_table(0, 0, len(self._lines), len(self._headers)-1,
98
+ {'header_row': True, 'data': xls_data, 'columns': xls_headers}
99
+ )
100
+ xls_worksheet.freeze_panes(1, 0)
101
+ xls_workbook.close()
102
+
103
+
104
+ class ArraysToExcel:
105
+
106
+ _sheets: Dict[str, 'ArraysToExcel.Sheet']
107
+
108
+ class Sheet:
109
+ def __init__(self, headers: List[str|ExcelHeader], force_all_wrap_text=True, sheet_color: Optional[str] = None, order_by: Optional[List[str]] = None, multivalues_cell_delimiter=' '):
110
+ self._headers: List[str|ExcelHeader] = headers
111
+ self._columns_count = len(headers)
112
+ self._lines = []
113
+ self._columns_wrap = []
114
+ self._color = sheet_color
115
+
116
+ self._order_by = order_by
117
+
118
+ self._multivalues_cell_delimiter = multivalues_cell_delimiter
119
+
120
+ self._headers_name_to_index = {}
121
+ self._headers_index_to_name = []
122
+ index = 0
123
+
124
+ for header_name in headers:
125
+ self._columns_wrap.append(force_all_wrap_text)
126
+
127
+ if type(header_name) is str:
128
+ self._headers_index_to_name.append(header_name)
129
+ self._headers_name_to_index[header_name] = index
130
+ else:
131
+ header_name['nice_name'] = header_name.get('nice_name', header_name['name'])
132
+ self._headers_index_to_name.append(header_name['name'])
133
+ self._headers_name_to_index[header_name['name']] = index
134
+
135
+ wrap = header_name.get('wrap_text')
136
+ if wrap is not None and not wrap:
137
+ self._columns_wrap[len(self._columns_wrap)-1] = False
138
+
139
+ index += 1
140
+
141
+ def write_to_csv(self, filename: str,
142
+ ):
143
+ headers: List[str] = []
144
+ for header in self._headers:
145
+ if type(header) is str:
146
+ headers.append(header)
147
+ continue
148
+ if 'nice_name' in header:
149
+ headers.append(header['nice_name'])
150
+ continue
151
+ headers.append(header['name'])
152
+
153
+ headers_id: List[str] = []
154
+ for header in self._headers:
155
+ if type(header) is str:
156
+ headers_id.append(header)
157
+ continue
158
+ headers_id.append(header['name'])
159
+
160
+
161
+ exporter = ArrayToExport(headers)
162
+
163
+ for line in self._lines:
164
+ row = []
165
+ for header in headers_id:
166
+ row.append(line[self._headers_name_to_index[header]])
167
+ exporter.add_line_from_list(row)
168
+
169
+ exporter.write_to_csv(filename)
170
+
171
+ def columns_count(self):
172
+ return len(self._headers)
173
+
174
+ def lines_count(self):
175
+ return len(self._lines)
176
+
177
+ def reorder_lines(self, order_by: List[str]):
178
+ self._lines = sorted(self._lines, key=lambda x: [x[self._headers_name_to_index[header_name]] for header_name in order_by])
179
+
180
+ def add_line_from_object(self, record):
181
+ new_line = []
182
+ for header in self._headers:
183
+ if type(header) is str:
184
+ new_line.append(record.get(header))
185
+ else:
186
+ new_line.append(record.get(header['name']))
187
+
188
+ self._lines.append(new_line)
189
+
190
+ def add_line_from_list_of_objects(self, list_of_objects):
191
+ for record in list_of_objects:
192
+ self.add_line_from_object(record)
193
+
194
+ def add_line_from_list(self, line: list):
195
+ if len(line) != self._columns_count:
196
+ raise pylo.PyloEx("line length ({}) does not match the number of columns ({})".format(len(line), self._columns_count))
197
+ self._lines.append(line)
198
+
199
+ def add_to_document(self, xls_workbook: xlsxwriter.Workbook, sheet_name: str):
200
+
201
+ def find_length(some_text: str) -> int:
202
+ if type(some_text) is bool or some_text is None:
203
+ return 0
204
+ if type(some_text) is int:
205
+ return len(str(some_text))
206
+
207
+ str_length = 0
208
+ split = some_text.split("\n")
209
+ for part in split:
210
+ if len(part) > str_length:
211
+ str_length = len(part)
212
+
213
+ return str_length
214
+
215
+
216
+ # Data may need to be sorted
217
+ if self._order_by is not None and len(self._order_by) > 0:
218
+ self._lines = sorted(self._lines, key=lambda x: [x[self._headers_name_to_index[header_name]] for header_name in self._order_by])
219
+ # print("********* Sorted by {}".format(self._order_by))
220
+
221
+ xls_worksheet = xls_workbook.add_worksheet(sheet_name)
222
+ if self._color is not None:
223
+ xls_worksheet.tab_color = self._color
224
+ xls_headers = []
225
+ xls_data = []
226
+
227
+ columns_max_width = []
228
+ for header in self._headers:
229
+ columns_max_width.append(0)
230
+
231
+ for line in self._lines:
232
+ new_line = []
233
+ item_index = 0
234
+ for item in line:
235
+ if type(item) is list:
236
+ new_line.append(pylo.string_list_to_text(item, self._multivalues_cell_delimiter))
237
+ else:
238
+ new_line.append(item)
239
+
240
+ length = find_length(new_line[item_index])
241
+ if length > columns_max_width[item_index]:
242
+ columns_max_width[item_index] = length
243
+ item_index += 1
244
+
245
+ xls_data.append(new_line)
246
+
247
+ header_index = 0
248
+ for header in self._headers:
249
+ cell_format = xls_workbook.add_format()
250
+ cell_format.set_text_wrap(self._columns_wrap[header_index])
251
+ cell_format.set_valign('vcenter')
252
+
253
+ header_max_width_setting = None
254
+
255
+ if type(header) is str:
256
+ xls_headers.append({'header': header, 'format': cell_format})
257
+ column_name_length = len(header) + 2 # add 2 for dropdown menus
258
+ else:
259
+ column_name = header.get('nice_name') or header.get('name')
260
+ xls_headers.append({'header': column_name, 'format': cell_format})
261
+ column_name_length = len(column_name) + 2 # add 2 for dropdown menus
262
+ header_max_width_setting = header.get('max_width')
263
+
264
+ # default is to use width=longest string
265
+ column_width = columns_max_width[header_index]+1
266
+
267
+ if column_width < column_name_length:
268
+ column_width = column_name_length
269
+
270
+ if header_max_width_setting is not None:
271
+ if header_max_width_setting is None or header_max_width_setting == 'auto':
272
+ pass
273
+ elif columns_max_width[header_index] > header_max_width_setting:
274
+ column_width = header_max_width_setting
275
+
276
+ #print("column '{}' width={} vs setting={} vs calculated={}".format(header_index, column_width, header_max_width_setting, columns_max_width[header_index]))
277
+
278
+ xls_worksheet.set_column(header_index, header_index, width=column_width*1.1)
279
+
280
+ header_index += 1
281
+
282
+ if len(self._lines) > 0:
283
+ xls_table = xls_worksheet.add_table(0, 0, len(self._lines), len(self._headers)-1,
284
+ {'header_row': True, 'data': xls_data, 'columns': xls_headers}
285
+ )
286
+ else:
287
+ fake_data = []
288
+ for header in self._headers:
289
+ fake_data.append(None)
290
+
291
+ xls_table = xls_worksheet.add_table(0, 0, 1, len(self._headers)-1,
292
+ {'header_row': True, 'data': [fake_data], 'columns': xls_headers}
293
+ )
294
+ xls_worksheet.freeze_panes(1, 0)
295
+
296
+ def __init__(self):
297
+ self._sheets = {}
298
+
299
+ def create_sheet(self, name: str, headers, force_all_wrap_text: bool = True, sheet_color: Optional[str] = None,
300
+ order_by: Optional[List[str]] = None, multivalues_cell_delimiter: str = ' ') -> Sheet:
301
+ if name in self._sheets:
302
+ pylo.PyloEx("A sheet named '{}' already exists".format(name))
303
+
304
+ self._sheets[name] = ArraysToExcel.Sheet(headers, force_all_wrap_text=force_all_wrap_text,
305
+ sheet_color=sheet_color, order_by=order_by,
306
+ multivalues_cell_delimiter=multivalues_cell_delimiter)
307
+ return self._sheets[name]
308
+
309
+ def write_to_excel(self, filename, multivalues_cell_delimiter=' '):
310
+ xls_workbook = xlsxwriter.Workbook(filename)
311
+
312
+ for sheet_name, sheet_object in self._sheets.items():
313
+ sheet_object.add_to_document(xls_workbook, sheet_name)
314
+
315
+ xls_workbook.close()
316
+
317
+ def add_line_from_object(self, record, sheet_name: str):
318
+ self._sheets[sheet_name].add_line_from_object(record)
319
+
320
+ def add_line_from_list_of_objects(self, list_of_objects, sheet_name: str):
321
+ self._sheets[sheet_name].add_line_from_list_of_objects(list_of_objects)
322
+
323
+ def add_line_from_list(self, line: list, sheet_name: str):
324
+ self._sheets[sheet_name].add_line_from_list(line)
325
+
326
+
327
+
328
+ class CsvExcelToObject:
329
+
330
+ def __init__(self, filename: str, expected_headers=None, csv_delimiter=',', csv_quotechar='"', strict_headers=False, excel_sheet_name=None):
331
+
332
+ self._detected_headers = []
333
+ self._header_index_to_name = []
334
+ self._raw_lines = []
335
+ self._objects = []
336
+ self._empty_lines_count = 0
337
+
338
+ if strict_headers and expected_headers is None:
339
+ pylo.PyloEx("CSV/Excel file cannot use strict_headers mode without specifying expected_headers")
340
+
341
+ if not os.path.exists(filename):
342
+ raise pylo.PyloEx("File '{}' does not exist".format(filename))
343
+
344
+ optional_headers = []
345
+ mandatory_headers_dict = {}
346
+ for header_infos in expected_headers:
347
+ value = header_infos.get('optional')
348
+ if value is None or value is True:
349
+ optional_headers.append(header_infos)
350
+ else:
351
+ mandatory_headers_dict[header_infos['name']] = header_infos
352
+
353
+ file_base, file_extension = os.path.splitext(filename)
354
+ file_extension = file_extension.lower()
355
+
356
+ if file_extension == '.csv':
357
+ with open(filename) as csv_file:
358
+ csv_reader = csv.reader(csv_file, delimiter=csv_delimiter, quotechar=csv_quotechar)
359
+ row_count = 0
360
+ for row in csv_reader:
361
+
362
+ # this is Headers
363
+ if row_count == 0:
364
+ for item in row:
365
+ if item is None or len(item) < 1:
366
+ raise pylo.PyloEx('CSV headers has blank fields, this is not supported')
367
+ self._detected_headers.append(item.lower())
368
+ if strict_headers and item.lower() not in mandatory_headers_dict:
369
+ raise pylo.PyloEx("CSV/Excel headers have an unexpected header named '{}'".format(item))
370
+
371
+ missing_headers = mandatory_headers_dict.copy()
372
+ for header_name in self._detected_headers:
373
+ self._header_index_to_name.append(header_name)
374
+ if header_name in missing_headers:
375
+ del missing_headers[header_name]
376
+ if len(missing_headers) > 0:
377
+ raise pylo.PyloEx('CSV is missing the following mandatory headers: {}'.format(pylo.string_list_to_text(missing_headers.keys())))
378
+
379
+ # this is DATA
380
+ else:
381
+ if len(self._detected_headers) != len(row):
382
+ raise pylo.PyloEx('CSV line #{} doesnt have the same fields ({}) count than the headers ({}), is it empty?'.format(row_count+1,
383
+ len(self._detected_headers),
384
+ len(row)))
385
+
386
+ self._raw_lines.append(row)
387
+ new_object = {'*line*': row_count+1}
388
+ self._objects.append(new_object)
389
+ row_index = 0
390
+ for item in row:
391
+ new_object[self._detected_headers[row_index]] = item
392
+ row_index += 1
393
+
394
+ # handling missing optional columns
395
+ for opt_header in optional_headers:
396
+ if opt_header['name'] not in new_object:
397
+ if 'default' in opt_header:
398
+ new_object[opt_header['name']] = opt_header['default']
399
+ else:
400
+ new_object[opt_header['name']] = ''
401
+
402
+ row_count += 1
403
+ elif file_extension == '.xlsx':
404
+ #workbook = openpyxl.load_workbook(filename, read_only=True)
405
+ workbook = openpyxl.load_workbook(filename)
406
+ # print("workbook has {} worksheets".format(len(workbook.worksheets)))
407
+ if len(workbook.worksheets) < 1:
408
+ raise pylo.PyloEx("Excel file has no Worksheet")
409
+
410
+ source_worksheet = workbook.worksheets[0]
411
+
412
+ if excel_sheet_name is not None:
413
+ source_worksheet = workbook.get_sheet_by_name(excel_sheet_name)
414
+ if source_worksheet is None:
415
+ raise pylo.PyloEx("Cannot find a Worksheet named '{}' in Excel file '{}'".format(excel_sheet_name, filename))
416
+
417
+ # print("\n\nmax_col {} max_row {}\n\n".format(source_worksheet.max_column,source_worksheet.max_row))
418
+
419
+ for row_count in range(1, source_worksheet.max_row+1):
420
+ # this is Headers
421
+ if row_count == 1:
422
+ for col_index in range(1, source_worksheet.max_column+1):
423
+ item = source_worksheet.cell(row_count, col_index).value
424
+ if item is None or len(item) < 1:
425
+ raise pylo.PyloEx('Excel headers has blank fields, this is not supported')
426
+ self._detected_headers.append(item.lower())
427
+ if strict_headers and item.lower() not in mandatory_headers_dict:
428
+ raise pylo.PyloEx("CSV/Excel headers have an unexpected header named '{}'".format(item))
429
+
430
+ missing_headers = mandatory_headers_dict.copy()
431
+ for header_name in self._detected_headers:
432
+ self._header_index_to_name.append(header_name)
433
+ if header_name in missing_headers:
434
+ del missing_headers[header_name]
435
+ if len(missing_headers) > 0:
436
+ raise pylo.PyloEx('Excel file is missing the following mandatory headers: {}'.format(pylo.string_list_to_text(missing_headers.keys())))
437
+
438
+ # This is DATA
439
+ else:
440
+ new_object = {'*line*': row_count}
441
+
442
+ some_fields_have_data = False
443
+ for col_index in range(1, source_worksheet.max_column+1):
444
+ item = source_worksheet.cell(row_count, col_index).value
445
+ new_object[self._detected_headers[col_index-1]] = item
446
+ if item is not None and (type(item) is int or type(item) is bool or len(item) > 0):
447
+ some_fields_have_data = True
448
+
449
+ if not some_fields_have_data:
450
+ self._empty_lines_count += 1
451
+ continue
452
+
453
+ self._objects.append(new_object)
454
+
455
+ # handling missing optional columns
456
+ for opt_header in optional_headers:
457
+ if opt_header['name'] not in new_object:
458
+ if 'default' in opt_header:
459
+ new_object[opt_header['name']] = opt_header['default']
460
+ else:
461
+ new_object[opt_header['name']] = ''
462
+
463
+ else:
464
+ raise pylo.PyloEx("Unsupported file extension '{}' in filename {}".format(file_extension, filename))
465
+
466
+
467
+ def count_lines(self):
468
+ return len(self._objects)
469
+
470
+ def count_empty_lines(self):
471
+ return self._empty_lines_count
472
+
473
+ def count_columns(self):
474
+ return len(self._detected_headers)
475
+
476
+ def objects(self):
477
+ return list(self._objects)
478
+
479
+ def save_to_csv(self, filename: str, fields_filter: List[Any]):
480
+ headers = []
481
+ for field in fields_filter:
482
+ headers.append(field['name'])
483
+
484
+ exporter = ArrayToExport(headers)
485
+
486
+ for obj in self._objects:
487
+ row = []
488
+ for header in headers:
489
+ row.append(obj.get(header))
490
+ exporter.add_line_from_list(row)
491
+
492
+ exporter.write_to_csv(filename)
493
+
494
+ def save_to_excel(self, filename: str, fields_filter: list):
495
+ headers = []
496
+ for field in fields_filter:
497
+ headers.append(field['name'])
498
+
499
+ exporter = ArrayToExport(headers)
500
+
501
+ for obj in self._objects:
502
+ row = []
503
+ for header in headers:
504
+ row.append(obj.get(header))
505
+ exporter.add_line_from_list(row)
506
+
507
+ exporter.write_to_excel(filename)
508
+
@@ -0,0 +1,166 @@
1
+ import json
2
+ import os
3
+ import re
4
+ import time
5
+
6
+
7
+ def nice_json(json_obj):
8
+ return json.dumps(json_obj, indent=2, sort_keys=True)
9
+
10
+
11
+ def string_list_to_text(string_list, separator=',') -> str:
12
+ """
13
+
14
+ :type string_list: List[str]
15
+ :type separator: str
16
+ """
17
+ msg = ""
18
+ first = True
19
+ for stringItem in string_list:
20
+ if type(stringItem) is str:
21
+ str_to_print = stringItem
22
+ else:
23
+ str_to_print = stringItem.name
24
+
25
+ if not first:
26
+ msg += separator
27
+ first = False
28
+ msg += str_to_print
29
+ # print("list length {} and msg ='{}'".format(len(string_list), msg))
30
+ return msg
31
+
32
+
33
+ def obj_with_href_list_to_text(string_list, separator=',') -> str:
34
+ """
35
+
36
+ :type string_list: List[str]
37
+ :type separator: str
38
+ """
39
+ msg = ""
40
+ first = True
41
+ for stringItem in string_list:
42
+ str_to_print = stringItem.href
43
+
44
+ if not first:
45
+ msg += separator
46
+ first = False
47
+ msg += str_to_print
48
+ # print("list length {} and msg ='{}'".format(len(string_list), msg))
49
+ return msg
50
+
51
+
52
+ def file_clean(path, no_print=False):
53
+ if not no_print:
54
+ print(" * Cleaning file '{}' from previous runs... ".format(path), end='', flush=True)
55
+ if os.path.exists(path):
56
+ if not os.path.isfile(path):
57
+ raise Exception("Provided path '{}' is not a file!".format(path))
58
+ else:
59
+ os.remove(path)
60
+ print("OK!")
61
+
62
+
63
+ ___ipv4_pattern = re.compile(r"""
64
+ ^
65
+ (?:
66
+ # Dotted variants:
67
+ (?:
68
+ # Decimal 1-255 (no leading 0's)
69
+ [3-9]\d?|2(?:5[0-5]|[0-4]?\d)?|1\d{0,2}
70
+ |
71
+ 0x0*[0-9a-f]{1,2} # Hexadecimal 0x0 - 0xFF (possible leading 0's)
72
+ |
73
+ 0+[1-3]?[0-7]{0,2} # Octal 0 - 0377 (possible leading 0's)
74
+ )
75
+ (?: # Repeat 0-3 times, separated by a dot
76
+ \.
77
+ (?:
78
+ [3-9]\d?|2(?:5[0-5]|[0-4]?\d)?|1\d{0,2}
79
+ |
80
+ 0x0*[0-9a-f]{1,2}
81
+ |
82
+ 0+[1-3]?[0-7]{0,2}
83
+ )
84
+ ){0,3}
85
+ |
86
+ 0x0*[0-9a-f]{1,8} # Hexadecimal notation, 0x0 - 0xffffffff
87
+ |
88
+ 0+[0-3]?[0-7]{0,10} # Octal notation, 0 - 037777777777
89
+ |
90
+ # Decimal notation, 1-4294967295:
91
+ 429496729[0-5]|42949672[0-8]\d|4294967[01]\d\d|429496[0-6]\d{3}|
92
+ 42949[0-5]\d{4}|4294[0-8]\d{5}|429[0-3]\d{6}|42[0-8]\d{7}|
93
+ 4[01]\d{8}|[1-3]\d{0,9}|[4-9]\d{0,8}
94
+ )
95
+ $
96
+ """, re.VERBOSE | re.IGNORECASE)
97
+
98
+
99
+ def is_valid_ipv4(ip):
100
+ """Validates IPv4 addresses.
101
+ """
102
+ return ___ipv4_pattern.match(ip) is not None
103
+
104
+
105
+ ___ipv6_pattern = re.compile(r"""
106
+ ^
107
+ \s* # Leading whitespace
108
+ (?!.*::.*::) # Only a single whildcard allowed
109
+ (?:(?!:)|:(?=:)) # Colon iff it would be part of a wildcard
110
+ (?: # Repeat 6 times:
111
+ [0-9a-f]{0,4} # A group of at most four hexadecimal digits
112
+ (?:(?<=::)|(?<!::):) # Colon unless preceeded by wildcard
113
+ ){6} #
114
+ (?: # Either
115
+ [0-9a-f]{0,4} # Another group
116
+ (?:(?<=::)|(?<!::):) # Colon unless preceeded by wildcard
117
+ [0-9a-f]{0,4} # Last group
118
+ (?: (?<=::) # Colon iff preceeded by exacly one colon
119
+ | (?<!:) #
120
+ | (?<=:) (?<!::) : #
121
+ ) # OR
122
+ | # A v4 address with NO leading zeros
123
+ (?:25[0-4]|2[0-4]\d|1\d\d|[1-9]?\d)
124
+ (?: \.
125
+ (?:25[0-4]|2[0-4]\d|1\d\d|[1-9]?\d)
126
+ ){3}
127
+ )
128
+ \s* # Trailing whitespace
129
+ $
130
+ """, re.VERBOSE | re.IGNORECASE | re.DOTALL)
131
+
132
+
133
+ def is_valid_ipv6(ip):
134
+ """Validates IPv6 addresses.
135
+ """
136
+ #print("testing ({})".format(ip))
137
+ return ___ipv6_pattern.match(ip) is not None
138
+
139
+
140
+ def hostname_from_fqdn(fqdn: str):
141
+ return fqdn.split('.')[0]
142
+
143
+
144
+ __clocks_start = {}
145
+ __clocks_end = {}
146
+
147
+
148
+ def clock_start(name:str = 'default'):
149
+ __clocks_start[name] = time.time()
150
+
151
+
152
+ def clock_stop(name:str = 'default'):
153
+ __clocks_end[name] = time.time()
154
+
155
+
156
+ import functools
157
+
158
+
159
+ def clock_elapsed_str(name:str = 'default'):
160
+ t = time.time()-__clocks_start[name]
161
+ return "%d:%02d:%02d.%03d" % \
162
+ functools.reduce(lambda ll,b : divmod(ll[0],b) + ll[1:],
163
+ [(t*1000,),1000,60,60])
164
+ return "{}".format(time.time()-__clocks_start[name])
165
+
166
+