SankeyExcelParser 1.0.0b0__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. SankeyExcelParser/__init__.py +0 -0
  2. SankeyExcelParser/io_excel.py +1867 -0
  3. SankeyExcelParser/io_excel_constants.py +811 -0
  4. SankeyExcelParser/sankey.py +3138 -0
  5. SankeyExcelParser/sankey_utils/__init__.py +0 -0
  6. SankeyExcelParser/sankey_utils/data.py +1118 -0
  7. SankeyExcelParser/sankey_utils/excel_source.py +31 -0
  8. SankeyExcelParser/sankey_utils/flux.py +344 -0
  9. SankeyExcelParser/sankey_utils/functions.py +278 -0
  10. SankeyExcelParser/sankey_utils/node.py +340 -0
  11. SankeyExcelParser/sankey_utils/protos/__init__.py +0 -0
  12. SankeyExcelParser/sankey_utils/protos/flux.py +84 -0
  13. SankeyExcelParser/sankey_utils/protos/node.py +386 -0
  14. SankeyExcelParser/sankey_utils/protos/sankey_object.py +135 -0
  15. SankeyExcelParser/sankey_utils/protos/tag_group.py +95 -0
  16. SankeyExcelParser/sankey_utils/sankey_object.py +165 -0
  17. SankeyExcelParser/sankey_utils/table_object.py +37 -0
  18. SankeyExcelParser/sankey_utils/tag.py +95 -0
  19. SankeyExcelParser/sankey_utils/tag_group.py +206 -0
  20. SankeyExcelParser/su_trace.py +239 -0
  21. SankeyExcelParser/tests/integration/__init__.py +0 -0
  22. SankeyExcelParser/tests/integration/test_base.py +356 -0
  23. SankeyExcelParser/tests/integration/test_run_check_input.py +100 -0
  24. SankeyExcelParser/tests/integration/test_run_conversions.py +96 -0
  25. SankeyExcelParser/tests/integration/test_run_load_input.py +94 -0
  26. SankeyExcelParser/tests/unit/__init__.py +0 -0
  27. SankeyExcelParser-1.0.0b0.data/scripts/run_parse_and_write_excel.py +155 -0
  28. SankeyExcelParser-1.0.0b0.data/scripts/run_parse_excel.py +115 -0
  29. SankeyExcelParser-1.0.0b0.dist-info/METADATA +113 -0
  30. SankeyExcelParser-1.0.0b0.dist-info/RECORD +32 -0
  31. SankeyExcelParser-1.0.0b0.dist-info/WHEEL +5 -0
  32. SankeyExcelParser-1.0.0b0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,340 @@
1
+ """
2
+ Author : Vincent LE DOZE
3
+ Date : 31/05/23
4
+
5
+ This file contains descriptions for Node class
6
+
7
+ """
8
+
9
+ # Local modules -----------------------------------------------------
10
+ from SankeyExcelParser.sankey_utils.protos.flux import _ProtoFlux
11
+ from SankeyExcelParser.sankey_utils.protos.node import _ProtoNode
12
+
13
+
14
+ # CLASS ----------------------------------------------------------------------------
15
+ class Node(_ProtoNode):
16
+ """
17
+ Define a node object.
18
+ Inherits from `_ProtoNode`, but add methods to deal with other Nodes.
19
+ """
20
+
21
+ def __init__(
22
+ self,
23
+ name: str,
24
+ level: int,
25
+ **kwargs
26
+ ):
27
+ # Init super
28
+ _ProtoNode.__init__(self, name, level)
29
+ # Add constructor values
30
+ self.update(**kwargs)
31
+
32
+ def update(
33
+ self,
34
+ **kwargs
35
+ ):
36
+ for key, value in kwargs.items():
37
+ setattr(self, key, value)
38
+
39
+ @property
40
+ def children_ids(self):
41
+ if not self.has_at_least_one_child():
42
+ return [[]]
43
+ return [[_.id for _ in grp] for grp in self._children_grps if len(grp) > 0]
44
+
45
+ @property
46
+ def parents_ids(self):
47
+ return [_.id for _ in self._parents]
48
+
49
+ def add_child(self, node: _ProtoNode, childrengrp_id: int = -1):
50
+ """
51
+ Add child to a children list.
52
+
53
+ Parameters
54
+ ----------
55
+ :param node: Child node to add.
56
+ :type node: _ProtoNode
57
+
58
+ :param childrengrp_id: Children group in which we should add child to.
59
+ :type childrengrp_id: int, optionnal (default=-1)
60
+ """
61
+ # Verify that we don't already have that child
62
+ # Add new groupe
63
+ if self._create_new_children_grp:
64
+ self._children_grps.append([])
65
+ self._create_new_children_grp = False
66
+ # Secure childgroup index
67
+ if childrengrp_id > 0:
68
+ while childrengrp_id >= len(self._children_grps):
69
+ self._children_grps.append([])
70
+ # Protection
71
+ if node not in self._children_grps[childrengrp_id]:
72
+ # Add child
73
+ self._children_grps[childrengrp_id].append(node)
74
+ # Add self to child's parent
75
+ node._add_parent(self)
76
+
77
+ def create_new_children_group(self):
78
+ self._create_new_children_grp = True
79
+
80
+ def has_at_least_one_child(self):
81
+ for _ in self._children_grps:
82
+ if len(_) > 0:
83
+ return True
84
+ return False
85
+
86
+ def is_child_of_given_node(self, node: _ProtoNode):
87
+ return (self in node.parents)
88
+
89
+ def get_set_of_all_base_children(self):
90
+ if self.has_at_least_one_child():
91
+ children_set = set()
92
+ for children_grp in self._children_grps:
93
+ for child in children_grp:
94
+ children_set |= child.get_set_of_all_base_children()
95
+ return children_set
96
+ return set([self])
97
+
98
+ def autocompute_level_and_children_levels(self, min_level=1):
99
+ """
100
+ Autocompute level based on parenthood leveling.
101
+ Returns max level that has been reached from children.
102
+ """
103
+ # Update own level
104
+ self._level = max(self._level, min_level)
105
+ # Init max level value
106
+ max_level = self._level
107
+ # Update sub-levels
108
+ for children_grp in self._children_grps:
109
+ # Secure: Start from a common min level for given children grp
110
+ min_children_level = min_level + 1
111
+ for child in children_grp:
112
+ min_children_level = max(child.level, min_children_level)
113
+ # Propagate level computing
114
+ for child in children_grp:
115
+ max_children_level = \
116
+ child.autocompute_level_and_children_levels(min_level=min_children_level)
117
+ max_level = max(max_children_level, max_level)
118
+ # Return max level
119
+ return max_level
120
+
121
+ def _add_parent(self, node: _ProtoNode):
122
+ """
123
+ Add parent.
124
+
125
+ Parameters
126
+ ----------
127
+ :param node: Parent node to add.
128
+ :type node: _ProtoNode
129
+ """
130
+ if node not in self._parents:
131
+ self._parents.append(node)
132
+
133
+ def has_parents(self):
134
+ return len(self._parents) > 0
135
+
136
+ def is_parent_of_given_node(self, node: _ProtoNode):
137
+ return node.is_child_of_given_node(self)
138
+
139
+ def add_input_flux(self, flux: _ProtoFlux):
140
+ self._input_flux.append(flux)
141
+
142
+ def add_output_flux(self, flux: _ProtoFlux):
143
+ self._output_flux.append(flux)
144
+
145
+ def get_flux_from_given_node(self, node: _ProtoNode):
146
+ """
147
+ Return the flux node->self
148
+
149
+ Parameters
150
+ ----------
151
+ :param node: Node where flux must arrive from
152
+ :type node: _ProtoNode
153
+
154
+ Returns
155
+ -------
156
+ :return: Flux that as been ask if found, otherwise None
157
+ :rtype: _ProtoFlux | None
158
+ """
159
+ for flux in self._input_flux:
160
+ if flux.orig == node:
161
+ return flux
162
+ return None
163
+
164
+ def get_flux_to_given_node(self, node: _ProtoNode):
165
+ """
166
+ Return the flux self->node
167
+
168
+ Parameters
169
+ ----------
170
+ :param node: Node where flux must go to
171
+ :type node: _ProtoNode
172
+
173
+ Returns
174
+ -------
175
+ :return: Flux that as been ask if found, otherwise None
176
+ :rtype: _ProtoFlux | None
177
+ """
178
+ for flux in self._output_flux:
179
+ if flux.dest == node:
180
+ return flux
181
+ return None
182
+
183
+ def update_table(
184
+ self,
185
+ level: int,
186
+ taggs_names: list,
187
+ extra_infos_names: list,
188
+ lineages_processed: list,
189
+ lineages_tables: list,
190
+ current_lineage_table: list,
191
+ lineages_entries,
192
+ current_lineage_entries,
193
+ lineages_entries__levels,
194
+ current_lineage_entries__levels
195
+ ):
196
+ """
197
+ Update a panda table with this node infos.
198
+ The columns are organized as :
199
+
200
+ 1. Level
201
+ 2. Name
202
+ 3. Mat balance
203
+ 4. Color
204
+ 5. All node tags (multiple columns) : for each column we have the respective tags or None
205
+ 6. Definition
206
+ 14. All remaining extra infos (if present, multiple columns)
207
+
208
+ Parameters
209
+ ----------
210
+ :param level: Level that will be indicated on table for the node.
211
+ Can be different form actual level because of multiplicity of parents
212
+ :type level: int
213
+
214
+ :param taggs_names: List of tag groups for node tags columns
215
+ :type taggs_names: list[str] | list[TagGroup]
216
+
217
+ :param extra_infos_names: List of extra infos to search for extra infos columns
218
+ :type extra_infos_names: list[str]
219
+
220
+ :param lineages_processed: List of children grp that have already been added to table
221
+ :type lineages_processed: list[list[Node]] (modified)
222
+
223
+ :param lineages_tables: List of all tables (2-D list) of all possible lineages of nodes
224
+ :type lineages_tables: list[list[list[str]]] (modified)
225
+
226
+ :param current_lineage_table: Table (2-D list) containing infos of all current lineage related nodes
227
+ :type current_lineage_table: list[list[str]] (modified)
228
+
229
+ :param lineages_entries:
230
+ List of all lists of nodes that have been added to lineages_tables.
231
+ Used to colorize table.
232
+ :type lineages_entries: list[list[Node]] (modified)
233
+
234
+ :param current_lineage_entries:
235
+ List of nodes that have been added to current_lineage_table.
236
+ Used to colorize table.
237
+ :type current_lineage_entries: list[Node] (modified)
238
+
239
+ :param lineages_entries__level:
240
+ List of all lists of nodes' levels that have been added to lineages_tables.
241
+ Used to colorize table.
242
+ :type lineages_entries: list[list[int]] (modified)
243
+
244
+ :param current_lineage_entries__level:
245
+ List of nodes' levels that have been added to current_lineage_table.
246
+ Used to colorize table.
247
+ :type current_lineage_entries: list[int] (modified)
248
+ """
249
+ # Create table line with corresponding data for self
250
+ line_node = [
251
+ level,
252
+ self.name,
253
+ self.mat_balance,
254
+ self.color]
255
+ # Add tags
256
+ line_node += self.get_tags_from_taggroups(
257
+ taggs_names, return_names_instead_of_refs=True)
258
+ # Add definition
259
+ line_node.append(self.definition)
260
+ # Add extra info cols if needed
261
+ for extra_info_name in extra_infos_names:
262
+ if extra_info_name in self.extra_infos.keys():
263
+ line_node.append(self.extra_infos[extra_info_name])
264
+ else:
265
+ line_node.append(None)
266
+ # Add line to the table
267
+ current_lineage_table.append(line_node)
268
+ current_lineage_entries.append(self)
269
+ current_lineage_entries__levels.append(level)
270
+ # If we have children for this node, we add them directly under
271
+ if self.has_at_least_one_child():
272
+ main_lineages_processed = False
273
+ # I do not pass by decorator here, because I need the pointer to childgroup for lineages_processed
274
+ for childgroup in self._children_grps:
275
+ # Pass already processed lineage
276
+ if childgroup in lineages_processed:
277
+ continue
278
+ # Recursively process children for main lineage (first children grp)
279
+ if not main_lineages_processed:
280
+ for child in childgroup:
281
+ child.update_table(
282
+ level+1,
283
+ taggs_names,
284
+ extra_infos_names,
285
+ lineages_processed,
286
+ lineages_tables,
287
+ current_lineage_table,
288
+ lineages_entries,
289
+ current_lineage_entries,
290
+ lineages_entries__levels,
291
+ current_lineage_entries__levels)
292
+ main_lineages_processed = True
293
+ else:
294
+ if len(childgroup) > 0: # Protection
295
+ # Start a new lineage (from level = 1)
296
+ new_line_node = line_node.copy()
297
+ new_line_node[0] = 1
298
+ new_lineage_table = [new_line_node]
299
+ lineages_tables.append(new_lineage_table)
300
+ # Update list of level / nodes for table colorization
301
+ new_lineage_entries = [self]
302
+ new_lineage_entries__levels = [1]
303
+ lineages_entries.append(new_lineage_entries)
304
+ lineages_entries__levels.append(new_lineage_entries__levels)
305
+ # Recursively process children for new lineage
306
+ for child in childgroup:
307
+ child.update_table(
308
+ 2,
309
+ taggs_names,
310
+ extra_infos_names,
311
+ lineages_processed,
312
+ lineages_tables,
313
+ new_lineage_table,
314
+ lineages_entries,
315
+ new_lineage_entries,
316
+ lineages_entries__levels,
317
+ new_lineage_entries__levels)
318
+ lineages_processed.append(childgroup)
319
+
320
+ def get_as_dict(self):
321
+ # Init output
322
+ output = {}
323
+ # Get values
324
+ output['name'] = self.name
325
+ output['tags'] = [
326
+ [_.group.name, _.name] for _ in self.tags]
327
+ output['parents'] = [_.name for _ in self.parents]
328
+ output['childrens'] = \
329
+ [[_.name for _ in grp]
330
+ for grp in self.children_grps]
331
+ output['mat_balance'] = self.mat_balance
332
+ output['color'] = self.color
333
+ output['definition'] = self.definition
334
+ return output
335
+
336
+ def __repr__(self):
337
+ s = '{}'.format(self._name)
338
+ for tag in self._tags:
339
+ s += ' | {}'.format(tag)
340
+ return s
File without changes
@@ -0,0 +1,84 @@
1
+ """
2
+ Author : Vincent LE DOZE
3
+ Date : 31/05/23
4
+
5
+ This file contains descriptions for proto Flux class
6
+
7
+ """
8
+
9
+ # Local modules -----------------------------------------------------
10
+ from SankeyExcelParser.sankey_utils.sankey_object import SankeyObject
11
+ from SankeyExcelParser.sankey_utils.protos.node import _ProtoNode
12
+
13
+
14
+ # CLASS ----------------------------------------------------------------------------
15
+ class _ProtoFlux(SankeyObject):
16
+ """
17
+ Define a prototype for flux object.
18
+ Does nothing except defining attributes.
19
+ Inherits from `SankeyObject`
20
+
21
+ Parameters
22
+ ----------
23
+ :param id: Flux id (standardized))
24
+ :type id: str
25
+
26
+ :param orig: Flux starting node
27
+ :type orig: _ProtoNode
28
+
29
+ :param dest: Flux ending node
30
+ :type dest: _ProtoNode
31
+
32
+ :param datas: All datas for the flux
33
+ :type datas: list [Data, ...]
34
+
35
+ :param results: All datas (as results) for the flux
36
+ :type results: list [Data, ...]
37
+ """
38
+
39
+ def __init__(
40
+ self,
41
+ orig: _ProtoNode,
42
+ dest: _ProtoNode,
43
+ **kwargs
44
+ ):
45
+ # Init super constructor
46
+ SankeyObject.__init__(self)
47
+ # Create attributs
48
+ self._id = orig.id+'---'+dest.id
49
+ self._orig = orig
50
+ self._dest = dest
51
+
52
+ @property
53
+ def id(self):
54
+ return self._id
55
+
56
+ @property
57
+ def orig(self):
58
+ return self._orig
59
+
60
+ @property
61
+ def dest(self):
62
+ return self._dest
63
+
64
+ @property
65
+ def natural_unit(self):
66
+ return self._orig.get_natural_unit()
67
+
68
+ @natural_unit.setter
69
+ def natural_unit(self, _):
70
+ # Unit apply only to origin
71
+ self._orig._add_natural_unit(_)
72
+
73
+ @property
74
+ def factor(self):
75
+ return self._orig.get_factor()
76
+
77
+ @factor.setter
78
+ def factor(self, _):
79
+ # Unit apply only to origin
80
+ self._orig.add_factor(_)
81
+
82
+ @property
83
+ def tooltips(self):
84
+ return self._orig.tooltips