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.
Files changed (32) hide show
  1. {table_stream-0.1.6 → table_stream-0.1.7}/PKG-INFO +1 -1
  2. {table_stream-0.1.6 → table_stream-0.1.7}/pyproject.toml +1 -1
  3. table_stream-0.1.7/table_stream/__init__.py +50 -0
  4. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/erros.py +66 -12
  5. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/hash_map.py +88 -23
  6. table_stream-0.1.7/table_stream/notifier.py +146 -0
  7. table_stream-0.1.7/table_stream/pattner/__init__.py +3 -0
  8. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/pattner/adapter.py +2 -3
  9. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sheet/load.py +36 -54
  10. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sheet/options.py +0 -1
  11. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sheet/parse.py +16 -17
  12. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sheet/save.py +35 -57
  13. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/state.py +48 -28
  14. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sysfiles.py +238 -61
  15. table_stream-0.1.7/table_stream/table.py +805 -0
  16. table_stream-0.1.7/table_stream/thread.py +126 -0
  17. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream.egg-info/PKG-INFO +1 -1
  18. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream.egg-info/SOURCES.txt +1 -2
  19. table_stream-0.1.6/table_stream/__init__.py +0 -12
  20. table_stream-0.1.6/table_stream/io.py +0 -228
  21. table_stream-0.1.6/table_stream/notifier.py +0 -170
  22. table_stream-0.1.6/table_stream/pattner/__init__.py +0 -7
  23. table_stream-0.1.6/table_stream/pattner/observer.py +0 -279
  24. table_stream-0.1.6/table_stream/thread.py +0 -138
  25. {table_stream-0.1.6 → table_stream-0.1.7}/README.md +0 -0
  26. {table_stream-0.1.6 → table_stream-0.1.7}/setup.cfg +0 -0
  27. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sheet/__init__.py +0 -0
  28. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/sheet/check_mod.py +0 -0
  29. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream/workbook.py +0 -0
  30. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream.egg-info/dependency_links.txt +0 -0
  31. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream.egg-info/requires.txt +0 -0
  32. {table_stream-0.1.6 → table_stream-0.1.7}/table_stream.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: table_stream
3
- Version: 0.1.6
3
+ Version: 0.1.7
4
4
  Summary: Tipos de dados e implementações para o uso em tabelas.
5
5
  Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "table_stream"
3
- version = "0.1.6"
3
+ version = "0.1.7"
4
4
  description = "Tipos de dados e implementações para o uso em tabelas."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -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, ABCMeta
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 ArrayList[T](list):
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](metaclass=ABCMeta):
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
- pass
203
+ raise NotImplementedError()
151
204
 
152
205
  @classmethod
153
- def from_map(cls, data: Any) -> HashMap:
154
- pass
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
- raise NotImplementedError
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('str').to_dict()
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
+
@@ -0,0 +1,3 @@
1
+ from .adapter import (
2
+ IMPLEMENTATION, ADAPTATIVE, ObjectAdapter
3
+ )
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
- from abc import ABC, abstractmethod, ABCMeta
3
- from typing import Any, TypeVar
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')