table-stream 0.1.6__tar.gz → 0.1.7__tar.gz
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.
- {table_stream-0.1.6 → table_stream-0.1.7}/PKG-INFO +1 -1
- {table_stream-0.1.6 → table_stream-0.1.7}/pyproject.toml +1 -1
- table_stream-0.1.7/table_stream/__init__.py +50 -0
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/erros.py +66 -12
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/hash_map.py +88 -23
- table_stream-0.1.7/table_stream/notifier.py +146 -0
- table_stream-0.1.7/table_stream/pattner/__init__.py +3 -0
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/pattner/adapter.py +2 -3
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sheet/load.py +36 -54
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sheet/options.py +0 -1
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sheet/parse.py +16 -17
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sheet/save.py +35 -57
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/state.py +48 -28
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sysfiles.py +238 -61
- table_stream-0.1.7/table_stream/table.py +805 -0
- table_stream-0.1.7/table_stream/thread.py +126 -0
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream.egg-info/PKG-INFO +1 -1
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream.egg-info/SOURCES.txt +1 -2
- table_stream-0.1.6/table_stream/__init__.py +0 -12
- table_stream-0.1.6/table_stream/io.py +0 -228
- table_stream-0.1.6/table_stream/notifier.py +0 -170
- table_stream-0.1.6/table_stream/pattner/__init__.py +0 -7
- table_stream-0.1.6/table_stream/pattner/observer.py +0 -279
- table_stream-0.1.6/table_stream/thread.py +0 -138
- {table_stream-0.1.6 → table_stream-0.1.7}/README.md +0 -0
- {table_stream-0.1.6 → table_stream-0.1.7}/setup.cfg +0 -0
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sheet/__init__.py +0 -0
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sheet/check_mod.py +0 -0
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/workbook.py +0 -0
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream.egg-info/dependency_links.txt +0 -0
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream.egg-info/requires.txt +0 -0
- {table_stream-0.1.6 → table_stream-0.1.7}/table_stream.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from .hash_map import (
|
|
2
|
+
HashMap, hashMapName, HashMapDataFrame, HashMapDict, ArrayList,
|
|
3
|
+
K, T, BaseObjetct
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
from .notifier import ResultNotifier, Notifier, Listener
|
|
7
|
+
|
|
8
|
+
from .thread import (
|
|
9
|
+
ControllerThread, ThreadStateValue, exceptionValue, stateName,
|
|
10
|
+
EventState, InvalidStateTransition,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from .sheet import (
|
|
14
|
+
SheetLoader, InterfaceSheetLoad, ParserData, CsvOptions, SplitData,
|
|
15
|
+
csvEncoding, csvSeparator, OptionsIOSheet, SaveData,
|
|
16
|
+
FactorySaveData, FactorySheetLoader, SheetType,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from .sysfiles import (
|
|
20
|
+
File, Directory, ContentFiles, JsonConvert, JsonData,
|
|
21
|
+
EnumDocuments, ExtensionDocuments, UserFileSystem, PathElement,
|
|
22
|
+
create_table_from_file, load_file_hash, HeaderMetaData, create_void_table_files,
|
|
23
|
+
hashFile
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
from .state import (
|
|
27
|
+
StateValue, EventState, ErrorState, FinshState, InvalidStateTransition
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
from .table import (
|
|
31
|
+
TableMap,
|
|
32
|
+
ColumnV,
|
|
33
|
+
RowH,
|
|
34
|
+
TableEmptyError,
|
|
35
|
+
EmptyRowError,
|
|
36
|
+
ColumnNotFoundError,
|
|
37
|
+
HeaderNotFoundError,
|
|
38
|
+
HeadersSizeNotIqualError,
|
|
39
|
+
concat_tables,
|
|
40
|
+
RowNotExistError,
|
|
41
|
+
TableData,
|
|
42
|
+
ListTablesEmptyError,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
from .erros import (
|
|
46
|
+
ColumnNotFoudError, ColumnNotIqualSizeError,
|
|
47
|
+
SizeTableError, EmptyRowError, RowNotExistError, TableEmptyError,
|
|
48
|
+
ListTablesEmptyError, LoadWorkbookError, NotImplementedModuleError,
|
|
49
|
+
HeaderNotFoundError, HeadersSizeNotIqualError
|
|
50
|
+
)
|
|
@@ -19,17 +19,18 @@ class ValueNotifyNullError(CoreException):
|
|
|
19
19
|
|
|
20
20
|
def __init__(self, message: str = 'Notificação nula...') -> None:
|
|
21
21
|
super().__init__(message)
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
|
|
23
|
+
|
|
24
24
|
class UnsuportedSheetError(CoreException):
|
|
25
25
|
|
|
26
26
|
def __init__(self, message: str = 'Planilha inválida...') -> None:
|
|
27
27
|
super().__init__(message)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# ============================================================#
|
|
31
31
|
# Erros relacionados a HashMap
|
|
32
|
-
|
|
32
|
+
# ============================================================#
|
|
33
|
+
|
|
33
34
|
class InvalidHashMapTableError(CoreException):
|
|
34
35
|
|
|
35
36
|
def __init__(self, message: str = 'HashMap inválido') -> None:
|
|
@@ -48,9 +49,9 @@ class SizeTableError(InvalidHashMapTableError):
|
|
|
48
49
|
super().__init__(message)
|
|
49
50
|
|
|
50
51
|
|
|
51
|
-
|
|
52
|
+
# ============================================================#
|
|
52
53
|
# Erros relacionados a planilhas
|
|
53
|
-
|
|
54
|
+
# ============================================================#
|
|
54
55
|
class UndefinedSheetIndex(CoreException):
|
|
55
56
|
|
|
56
57
|
def __init__(self, message: str = 'SheetIndexNames não foi definido') -> None:
|
|
@@ -62,18 +63,18 @@ class LoadWorkbookError(CoreException):
|
|
|
62
63
|
def __init__(self, message: str = 'Erro ao tentar ler Workbook') -> None:
|
|
63
64
|
super().__init__(message)
|
|
64
65
|
|
|
65
|
-
|
|
66
|
+
# ============================================================#
|
|
66
67
|
# Erros relacionados a arquivos/bytes de imagem (.png, .jpg, ...)
|
|
67
|
-
|
|
68
|
+
# ============================================================#
|
|
68
69
|
class InvalidSourceImageError(CoreException):
|
|
69
70
|
|
|
70
71
|
def __init__(self, message: str = 'Erro, use bytes de imagem') -> None:
|
|
71
72
|
super().__init__(message)
|
|
72
73
|
|
|
73
74
|
|
|
74
|
-
|
|
75
|
+
# ============================================================#
|
|
75
76
|
# Erros relacionados a módulos
|
|
76
|
-
|
|
77
|
+
# ============================================================#
|
|
77
78
|
class NotImplementedModuleError(CoreException):
|
|
78
79
|
|
|
79
80
|
def __init__(self, message: str = 'Erro, módulo não implementado') -> None:
|
|
@@ -97,6 +98,59 @@ class NotImplementedInvertColor(NotImplementedError):
|
|
|
97
98
|
def __init__(self, message: str = 'Adaptador InvertColor não implementado...') -> None:
|
|
98
99
|
super().__init__(message)
|
|
99
100
|
|
|
101
|
+
# ============================================================#
|
|
102
|
+
# Erros relacionados a tabelas
|
|
103
|
+
# ============================================================#
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class ColumnNotFoudError(ValueError):
|
|
107
|
+
|
|
108
|
+
def __init__(self, *args: object) -> None:
|
|
109
|
+
super().__init__(*args)
|
|
110
|
+
|
|
111
|
+
class ColumnNotIqualSizeError(ValueError):
|
|
112
|
+
|
|
113
|
+
def __init__(self, *args: object) -> None:
|
|
114
|
+
super().__init__(*args)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
class EmptyRowError(Exception):
|
|
118
|
+
|
|
119
|
+
def __init__(self, *args: object) -> None:
|
|
120
|
+
super().__init__(*args)
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
class TableEmptyError(Exception):
|
|
124
|
+
|
|
125
|
+
def __init__(self, *args: object) -> None:
|
|
126
|
+
super().__init__(*args)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class HeaderNotFoundError(Exception):
|
|
130
|
+
|
|
131
|
+
def __init__(self, *args: object) -> None:
|
|
132
|
+
super().__init__(*args)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class HeadersSizeNotIqualError(Exception):
|
|
136
|
+
|
|
137
|
+
def __init__(self, *args: object) -> None:
|
|
138
|
+
super().__init__(*args)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
class ListTablesEmptyError(ValueError):
|
|
142
|
+
|
|
143
|
+
def __init__(self, *args: object) -> None:
|
|
144
|
+
super().__init__(*args)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class ColumnNotFoundError(ValueError):
|
|
148
|
+
|
|
149
|
+
def __init__(self, *args: object) -> None:
|
|
150
|
+
super().__init__(*args)
|
|
100
151
|
|
|
101
152
|
|
|
153
|
+
class RowNotExistError(ValueError):
|
|
102
154
|
|
|
155
|
+
def __init__(self, *args: object) -> None:
|
|
156
|
+
super().__init__(*args)
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from abc import abstractmethod,
|
|
3
|
-
from typing import Any, Callable, TypeVar, Union, Literal
|
|
2
|
+
from abc import abstractmethod, ABC
|
|
3
|
+
from typing import Any, Callable, TypeVar, Union, Literal, TypeAlias
|
|
4
|
+
|
|
5
|
+
from table_stream.erros import ColumnNotIqualSizeError
|
|
6
|
+
|
|
4
7
|
import json
|
|
5
8
|
from pandas import DataFrame
|
|
6
9
|
|
|
@@ -10,49 +13,92 @@ K = TypeVar('K')
|
|
|
10
13
|
hashMapName = Literal['DATAFRAME', 'DICT']
|
|
11
14
|
|
|
12
15
|
|
|
13
|
-
class
|
|
16
|
+
class BaseObjetct(object):
|
|
17
|
+
|
|
18
|
+
def __init__(self) -> None:
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
def __repr__(self) -> str:
|
|
22
|
+
return f"{__class__.__name__}()"
|
|
14
23
|
|
|
24
|
+
def hash(self) -> int:
|
|
25
|
+
return self.__hash__()
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ArrayList[T](list):
|
|
29
|
+
|
|
15
30
|
def __init__(self, items: list[T] | None = None):
|
|
16
31
|
if items is None:
|
|
17
32
|
items = list()
|
|
18
33
|
super().__init__(items)
|
|
19
|
-
|
|
34
|
+
|
|
35
|
+
def diff(self, values: ArrayList[T]) -> ArrayList[T]:
|
|
36
|
+
final = ArrayList[T]()
|
|
37
|
+
|
|
38
|
+
for v in values:
|
|
39
|
+
if not values.contains(v):
|
|
40
|
+
final.add(v)
|
|
41
|
+
return final
|
|
42
|
+
|
|
43
|
+
def append(self, item: T) -> None:
|
|
44
|
+
return super().append(item)
|
|
45
|
+
|
|
46
|
+
def add(self, v: T) -> None:
|
|
47
|
+
self.append(v)
|
|
48
|
+
|
|
20
49
|
def set_items(self, items: list[T]):
|
|
21
50
|
self.clear()
|
|
22
51
|
super().__init__(items)
|
|
23
|
-
|
|
52
|
+
|
|
24
53
|
def for_each(self, func: Callable[[T], Any | None]) -> None:
|
|
25
54
|
for x in self: func(x)
|
|
26
|
-
|
|
55
|
+
|
|
27
56
|
def apply_command(self, func: Callable[[T], Any]) -> ArrayList[Any]:
|
|
57
|
+
"""
|
|
58
|
+
Retorna uma nova lista, cada elemento da nova lista será o retorno
|
|
59
|
+
da função func: Callable[[T], Any]
|
|
60
|
+
"""
|
|
28
61
|
return ArrayList([func(x) for x in self])
|
|
29
|
-
|
|
62
|
+
|
|
30
63
|
def size(self) -> int:
|
|
31
64
|
return len(self)
|
|
32
|
-
|
|
65
|
+
|
|
33
66
|
def empty(self) -> bool:
|
|
34
67
|
return self.size() == 0
|
|
35
|
-
|
|
68
|
+
|
|
36
69
|
def get_first(self) -> T:
|
|
37
70
|
return self[0]
|
|
38
71
|
|
|
39
72
|
def get_last(self) -> T:
|
|
40
73
|
return self[-1]
|
|
41
|
-
|
|
74
|
+
|
|
75
|
+
def get_element_at(self, idx: int) -> T:
|
|
76
|
+
return self[idx]
|
|
77
|
+
|
|
78
|
+
def replace(self, idx: int, new: T) -> None:
|
|
79
|
+
self[idx] = new
|
|
80
|
+
|
|
42
81
|
def hash(self) -> int:
|
|
43
82
|
return hash(tuple(self))
|
|
44
|
-
|
|
83
|
+
|
|
45
84
|
def contains(self, _o: T) -> bool:
|
|
46
85
|
for i in self:
|
|
47
86
|
if i == _o:
|
|
48
87
|
return True
|
|
49
88
|
return False
|
|
50
|
-
|
|
51
89
|
|
|
52
|
-
|
|
90
|
+
@classmethod
|
|
91
|
+
def from_string(cls, value: str, separator: str = " ") -> ArrayList[str]:
|
|
92
|
+
return cls(value.split(separator))
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# ========================================================#
|
|
53
96
|
# Base para HashMap().
|
|
54
|
-
|
|
55
|
-
class HashMap[K, T](
|
|
97
|
+
# ========================================================#
|
|
98
|
+
class HashMap[K, T](ABC):
|
|
99
|
+
|
|
100
|
+
def __init__(self) -> None:
|
|
101
|
+
super().__init__()
|
|
56
102
|
|
|
57
103
|
def __repr__(self) -> str:
|
|
58
104
|
return f"<HashMap()> {self.header()}"
|
|
@@ -65,6 +111,9 @@ class HashMap[K, T](metaclass=ABCMeta):
|
|
|
65
111
|
def size_header(self) -> int:
|
|
66
112
|
pass
|
|
67
113
|
|
|
114
|
+
def is_empty(self) -> bool:
|
|
115
|
+
return self.header().empty()
|
|
116
|
+
|
|
68
117
|
@abstractmethod
|
|
69
118
|
def __getitem__(self, key: K) -> T:
|
|
70
119
|
pass
|
|
@@ -144,33 +193,42 @@ class HashMap[K, T](metaclass=ABCMeta):
|
|
|
144
193
|
Converte o HashMap() para uma representação no formato dict() python.
|
|
145
194
|
"""
|
|
146
195
|
pass
|
|
196
|
+
|
|
197
|
+
@abstractmethod
|
|
198
|
+
def to_data_frame(self) -> DataFrame:
|
|
199
|
+
pass
|
|
147
200
|
|
|
148
201
|
@classmethod
|
|
149
202
|
def from_json(cls, data: str) -> HashMap:
|
|
150
|
-
|
|
203
|
+
raise NotImplementedError()
|
|
151
204
|
|
|
152
205
|
@classmethod
|
|
153
|
-
def from_map(cls, data:
|
|
154
|
-
|
|
206
|
+
def from_map(cls, data: dict) -> HashMap:
|
|
207
|
+
raise NotImplementedError()
|
|
155
208
|
|
|
156
209
|
|
|
157
210
|
class HashMapDict[K, T](HashMap):
|
|
158
|
-
|
|
211
|
+
|
|
159
212
|
def __init__(self, _mapping: dict[K, T] | None = None) -> None:
|
|
160
213
|
super().__init__()
|
|
161
214
|
if _mapping is None:
|
|
162
215
|
_mapping = dict()
|
|
216
|
+
|
|
163
217
|
self._mapping: dict[K, T] = _mapping
|
|
164
218
|
|
|
165
219
|
def __repr__(self) -> str:
|
|
166
220
|
return f"<{__class__.__name__}()>\n{self.get_real_hash_map()}"
|
|
167
221
|
|
|
222
|
+
@property
|
|
223
|
+
def map(self) -> dict[K, T]:
|
|
224
|
+
return self.get_real_hash_map()
|
|
225
|
+
|
|
168
226
|
def size_values(self) -> int:
|
|
169
227
|
return len(self._mapping.values())
|
|
170
228
|
|
|
171
229
|
def size_header(self) -> int:
|
|
172
230
|
return self.header().size()
|
|
173
|
-
|
|
231
|
+
|
|
174
232
|
def __getitem__(self, key: K) -> T:
|
|
175
233
|
return self._mapping[key]
|
|
176
234
|
|
|
@@ -229,14 +287,18 @@ class HashMapDict[K, T](HashMap):
|
|
|
229
287
|
for i in self.header():
|
|
230
288
|
final[str(i)] = str(self.get_value(i))
|
|
231
289
|
return final
|
|
290
|
+
|
|
291
|
+
def to_data_frame(self) -> DataFrame:
|
|
292
|
+
return DataFrame(dict(self._mapping))
|
|
232
293
|
|
|
233
294
|
|
|
234
295
|
class HashMapDataFrame[K, Series](HashMap):
|
|
235
296
|
|
|
236
|
-
def __init__(self, df: DataFrame=None) -> None:
|
|
297
|
+
def __init__(self, df: DataFrame | None = None) -> None:
|
|
237
298
|
super().__init__()
|
|
238
299
|
if df is None:
|
|
239
300
|
df = DataFrame()
|
|
301
|
+
|
|
240
302
|
self._df: DataFrame = df
|
|
241
303
|
|
|
242
304
|
def size_values(self) -> int:
|
|
@@ -273,7 +335,7 @@ class HashMapDataFrame[K, Series](HashMap):
|
|
|
273
335
|
return self._df[self.header().get_last()]
|
|
274
336
|
|
|
275
337
|
def set_last(self, value: T) -> None:
|
|
276
|
-
|
|
338
|
+
self._df[self.header().get_last()] = value
|
|
277
339
|
|
|
278
340
|
def set_value(self, key: K, value: Series) -> None:
|
|
279
341
|
self._df[key] = value
|
|
@@ -304,4 +366,7 @@ class HashMapDataFrame[K, Series](HashMap):
|
|
|
304
366
|
return self._df.astype(str).to_json(orient="columns", force_ascii=False, indent=4)
|
|
305
367
|
|
|
306
368
|
def to_map_str(self) -> dict[str, Any]:
|
|
307
|
-
return self._df.astype(
|
|
369
|
+
return self._df.astype(str).to_dict()
|
|
370
|
+
|
|
371
|
+
def to_data_frame(self) -> DataFrame:
|
|
372
|
+
return self._df.copy()
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# notifier.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
from abc import ABC, abstractmethod, ABCMeta
|
|
4
|
+
from typing import Any, Callable, Optional, Type, TypeVar, cast
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
VALUE = TypeVar("VALUE")
|
|
8
|
+
NOTIFIER = TypeVar('NOTIFIER', bound="Notifier")
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# ============================================================
|
|
12
|
+
# CHANGE NOTIFIER
|
|
13
|
+
# ============================================================
|
|
14
|
+
class Notifier[VALUE]:
|
|
15
|
+
|
|
16
|
+
def __init__(self) -> None:
|
|
17
|
+
#super().__init__()
|
|
18
|
+
self._listeners: list[Callable[[], None]] = []
|
|
19
|
+
|
|
20
|
+
def contains_listener(self, listener: Callable[[], None]) -> bool:
|
|
21
|
+
return listener in self._listeners
|
|
22
|
+
|
|
23
|
+
def add_listener(self, listener: Listener) -> None:
|
|
24
|
+
if listener not in self._listeners:
|
|
25
|
+
self._listeners.append(listener.receiver_notifier)
|
|
26
|
+
|
|
27
|
+
def remove_listener(self, listener: Callable[[], None]) -> None:
|
|
28
|
+
if listener in self._listeners:
|
|
29
|
+
self._listeners.remove(listener)
|
|
30
|
+
|
|
31
|
+
def notify_listeners(self) -> None:
|
|
32
|
+
for listener in self._listeners: #.copy():
|
|
33
|
+
listener()
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class ResultNotifier[VALUE](Notifier):
|
|
37
|
+
|
|
38
|
+
def __init__(self, value: VALUE) -> None:
|
|
39
|
+
super().__init__()
|
|
40
|
+
self._result: VALUE = value
|
|
41
|
+
|
|
42
|
+
def get_result(self) -> VALUE:
|
|
43
|
+
return self._result
|
|
44
|
+
|
|
45
|
+
def set_result(self, v: VALUE) -> None:
|
|
46
|
+
self._result = v
|
|
47
|
+
self.notify_listeners()
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def result(self) -> VALUE:
|
|
51
|
+
return self._result
|
|
52
|
+
|
|
53
|
+
@result.setter
|
|
54
|
+
def result(self, value: VALUE) -> None:
|
|
55
|
+
self._result = value
|
|
56
|
+
self.notify_listeners()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class ProgressOperation(ResultNotifier[float]):
|
|
60
|
+
|
|
61
|
+
def __init__(self, value: float = 0.0) -> None:
|
|
62
|
+
super().__init__(value)
|
|
63
|
+
self.initial_value: int = 0
|
|
64
|
+
self.final_value: int = 0
|
|
65
|
+
self.running: bool = False
|
|
66
|
+
self.current_text: str = None
|
|
67
|
+
|
|
68
|
+
def reset(self):
|
|
69
|
+
self.initial_value = 0
|
|
70
|
+
self.final_value = 0
|
|
71
|
+
self.running = False
|
|
72
|
+
self.current_text = None
|
|
73
|
+
|
|
74
|
+
def add_progress(self) -> None:
|
|
75
|
+
if not self.running:
|
|
76
|
+
raise RuntimeError("A execução está parada -> running = False")
|
|
77
|
+
|
|
78
|
+
self.initial_value += 1
|
|
79
|
+
self.calcule_percent()
|
|
80
|
+
|
|
81
|
+
def calcule_percent(self):
|
|
82
|
+
if self.final_value <= 0:
|
|
83
|
+
raise ValueError()
|
|
84
|
+
if self.initial_value > self.final_value:
|
|
85
|
+
raise ValueError(f"{__class__.__name__} o Valor final é maior que o valor inicial")
|
|
86
|
+
|
|
87
|
+
percent: float = round((self.initial_value / self.final_value) * 100, 2)
|
|
88
|
+
self.set_result(percent)
|
|
89
|
+
|
|
90
|
+
def init_operation(self, total: int):
|
|
91
|
+
self.reset()
|
|
92
|
+
self.final_value = total
|
|
93
|
+
self.running = True
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class Listener[NOTIFIER](ABC):
|
|
97
|
+
"""
|
|
98
|
+
Consumer(): observa um ChangeNotifier registrado no Provider() e
|
|
99
|
+
permite que o Widget/Element associado seja notificado (via
|
|
100
|
+
receiver_notifier) sempre que o estado observado mudar.
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
def __init__(self) -> None:
|
|
104
|
+
super().__init__()
|
|
105
|
+
self.func_read_notifier: Callable[[type[NOTIFIER]], NOTIFIER] = self._read_notifier
|
|
106
|
+
|
|
107
|
+
# Notifiers já observados por este Consumer (evita registrar o
|
|
108
|
+
# mesmo listener duas vezes a cada build(), e permite unwatch_all()).
|
|
109
|
+
self._watched: dict[type[NOTIFIER], NOTIFIER] = dict()
|
|
110
|
+
self.type_notifier: type[NOTIFIER] = None
|
|
111
|
+
|
|
112
|
+
def _read_notifier(self, type_notifier: type[NOTIFIER]) -> NOTIFIER:
|
|
113
|
+
return self._watched[type_notifier]
|
|
114
|
+
|
|
115
|
+
def read(self) -> NOTIFIER:
|
|
116
|
+
return self.func_read_notifier(self.type_notifier)
|
|
117
|
+
|
|
118
|
+
def watch(self, notifier: NOTIFIER) -> NOTIFIER:
|
|
119
|
+
self.type_notifier = type(notifier)
|
|
120
|
+
state: Notifier = cast(Notifier, notifier)
|
|
121
|
+
|
|
122
|
+
if self.type_notifier not in self._watched:
|
|
123
|
+
state.add_listener(self)
|
|
124
|
+
self._watched[self.type_notifier] = notifier
|
|
125
|
+
return notifier
|
|
126
|
+
|
|
127
|
+
def unwatch_all(self) -> None:
|
|
128
|
+
"""
|
|
129
|
+
Remove este Consumer de todos os notifiers observados.
|
|
130
|
+
Deve ser chamado no dispose() do Element associado, para evitar
|
|
131
|
+
que um notifier segure referência viva de um widget já destruído.
|
|
132
|
+
"""
|
|
133
|
+
notifier: Notifier
|
|
134
|
+
for notifier in self._watched.values():
|
|
135
|
+
notifier.remove_listener(self.receiver_notifier)
|
|
136
|
+
self._watched.clear()
|
|
137
|
+
|
|
138
|
+
@abstractmethod
|
|
139
|
+
def receiver_notifier(self) -> None:
|
|
140
|
+
"""
|
|
141
|
+
Callback chamado pelo ChangeNotifier observado. Subclasses
|
|
142
|
+
(ex: um ConsumerElement) devem sobrescrever isto para disparar
|
|
143
|
+
o rebuild do widget associado.
|
|
144
|
+
"""
|
|
145
|
+
pass
|
|
146
|
+
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
from abc import
|
|
3
|
-
from typing import
|
|
4
|
-
from table_stream.hash_map import ArrayList
|
|
2
|
+
from abc import abstractmethod, ABCMeta
|
|
3
|
+
from typing import TypeVar
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
ADAPTATIVE = TypeVar('ADAPTATIVE')
|