pyflutter-app 0.2.6__tar.gz → 0.2.8__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 (99) hide show
  1. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/PKG-INFO +1 -1
  2. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/cartas/__init__.py +1 -1
  3. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/cartas/_table_toi.py +19 -19
  4. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/cartas/relatorio.py +36 -36
  5. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/page_forms/common.py +18 -18
  6. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/page_forms/controller_forms.py +7 -7
  7. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/ocrlib/_table_ocr.py +83 -35
  8. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/ocrlib/relatorio_ocr.py +120 -32
  9. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyproject.toml +1 -1
  10. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/__init__.py +1 -0
  11. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/table.py +71 -2
  12. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/test.py +47 -7
  13. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/uv.lock +1 -1
  14. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/whatsapp_files/_table_whatsapp.py +5 -0
  15. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/whatsapp_files/common.py +9 -5
  16. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/whatsapp_files/stream_files.py +8 -5
  17. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/.gitignore +0 -0
  18. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/.idea/.gitignore +0 -0
  19. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/.idea/inspectionProfiles/Project_Default.xml +0 -0
  20. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/.idea/inspectionProfiles/profiles_settings.xml +0 -0
  21. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/.idea/misc.xml +0 -0
  22. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/.idea/modules.xml +0 -0
  23. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/.idea/pyflutter_app.iml +0 -0
  24. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/.idea/vcs.xml +0 -0
  25. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/README.md +0 -0
  26. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/cartas/common.py +0 -0
  27. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/cartas/erros.py +0 -0
  28. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/cartas/find_toi.py +0 -0
  29. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/cartas/util.py +0 -0
  30. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/__init__.py +0 -0
  31. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/__main__.py +0 -0
  32. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/assets/forms_config.json +0 -0
  33. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/config_app.py +0 -0
  34. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/home_page/__init__.py +0 -0
  35. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/home_page/_page_edit.py +0 -0
  36. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/home_page/controller.py +0 -0
  37. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/home_page/model.py +0 -0
  38. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/home_page/view.py +0 -0
  39. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/lib_toi.py +0 -0
  40. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/page_forms/Diagnorstico.txt +0 -0
  41. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/page_forms/__init__.py +0 -0
  42. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/page_forms/config.py +0 -0
  43. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/page_forms/diagnose_forms.py +0 -0
  44. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/page_forms/model_forms.py +0 -0
  45. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/page_forms/service.py +0 -0
  46. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/page_forms/view_forms.py +0 -0
  47. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/run_app_convert.py +0 -0
  48. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/table_widget.py +0 -0
  49. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/util.py +0 -0
  50. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/whatsapp/__init__.py +0 -0
  51. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/converter/whatsapp/model.py +0 -0
  52. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/export_app.sh +0 -0
  53. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/local_build/linux.sh +0 -0
  54. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/local_build/send.sh +0 -0
  55. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/main.py +0 -0
  56. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/mediator.py +0 -0
  57. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/mvc/controller.py +0 -0
  58. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/mvc/model.py +0 -0
  59. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/mvc/view.py +0 -0
  60. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/new-export_app.sh +0 -0
  61. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/ocrlib/__init__.py +0 -0
  62. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/ocrlib/_common.py +0 -0
  63. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/ocrlib/_pdf_convert.py +0 -0
  64. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/ocrlib/_tesseract.py +0 -0
  65. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/ocrlib/erros.py +0 -0
  66. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/ocrlib/export_ocr.sh +0 -0
  67. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/ocrlib/util.py +0 -0
  68. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/__init__.py +0 -0
  69. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/app.py +0 -0
  70. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/file_picker.py +0 -0
  71. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/navigator.py +0 -0
  72. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/scheduler.py +0 -0
  73. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/theme.py +0 -0
  74. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/ui/__init__.py +0 -0
  75. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/ui/buttons.py +0 -0
  76. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/ui/container.py +0 -0
  77. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/ui/core.py +0 -0
  78. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/ui/list_builder.py +0 -0
  79. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/ui/progress.py +0 -0
  80. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/ui/tables.py +0 -0
  81. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/pyflutter_ui/ui/widgets.py +0 -0
  82. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/erros.py +0 -0
  83. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/hash_map.py +0 -0
  84. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/notifier.py +0 -0
  85. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/pattner/__init__.py +0 -0
  86. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/pattner/adapter.py +0 -0
  87. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/sheet/__init__.py +0 -0
  88. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/sheet/check_mod.py +0 -0
  89. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/sheet/load.py +0 -0
  90. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/sheet/options.py +0 -0
  91. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/sheet/parse.py +0 -0
  92. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/sheet/save.py +0 -0
  93. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/state.py +0 -0
  94. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/sysfiles.py +0 -0
  95. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/thread.py +0 -0
  96. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/table_stream/workbook.py +0 -0
  97. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/whatsapp_files/__init__.py +0 -0
  98. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/whatsapp_files/erros.py +0 -0
  99. {pyflutter_app-0.2.6 → pyflutter_app-0.2.8}/whatsapp_files/util.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: pyflutter_app
3
- Version: 0.2.6
3
+ Version: 0.2.8
4
4
  Summary: Bibliotecas Python para conversão de documentos, interface e processamento de tabelas.
5
5
  Requires-Python: >=3.12
6
6
  Requires-Dist: opencv-python>=5.0.0.93
@@ -1,6 +1,6 @@
1
1
  from ._table_toi import (
2
2
  HeaderTOI,
3
- HeaderFormsTOI,
3
+ HeaderCartas,
4
4
  TableTOI,
5
5
  LocalEntregaCarta,
6
6
  TipoCarta,
@@ -45,7 +45,7 @@ class HeaderTOI(StrEnum):
45
45
  HASH_FILE = HeaderMetaData.HASH_FILE.value
46
46
 
47
47
 
48
- class HeaderFormsTOI(StrEnum):
48
+ class HeaderCartas(StrEnum):
49
49
  """
50
50
  Dados completos de uma entrega TOI, incluindo os metadados e
51
51
  caminho absoluto dos arquivos.
@@ -127,22 +127,22 @@ class BuilderTablesTOI(object):
127
127
  ]
128
128
  )
129
129
 
130
- self.default_cols_forms = ArrayList[HeaderFormsTOI].from_list(
130
+ self.default_cols_forms = ArrayList[HeaderCartas].from_list(
131
131
  [
132
- HeaderFormsTOI.UC,
133
- HeaderFormsTOI.TOI,
134
- HeaderFormsTOI.DATE,
135
- HeaderFormsTOI.YEAR,
136
- HeaderFormsTOI.MON,
137
- HeaderFormsTOI.DAY,
138
- HeaderFormsTOI.LOCAL_ENTREGA,
139
- HeaderFormsTOI.TIPO_DOC,
140
- HeaderFormsTOI.HASH_FILE,
141
- HeaderFormsTOI.IS_FILE,
142
- HeaderFormsTOI.FILE_BASENAME,
143
- HeaderFormsTOI.FILE_EXTENSION,
144
- HeaderFormsTOI.FULL_PATH,
145
- HeaderFormsTOI.SRC,
132
+ HeaderCartas.UC,
133
+ HeaderCartas.TOI,
134
+ HeaderCartas.DATE,
135
+ HeaderCartas.YEAR,
136
+ HeaderCartas.MON,
137
+ HeaderCartas.DAY,
138
+ HeaderCartas.LOCAL_ENTREGA,
139
+ HeaderCartas.TIPO_DOC,
140
+ HeaderCartas.HASH_FILE,
141
+ HeaderCartas.IS_FILE,
142
+ HeaderCartas.FILE_BASENAME,
143
+ HeaderCartas.FILE_EXTENSION,
144
+ HeaderCartas.FULL_PATH,
145
+ HeaderCartas.SRC,
146
146
  ]
147
147
  )
148
148
 
@@ -173,7 +173,7 @@ class BuilderTablesTOI(object):
173
173
  )
174
174
  return tb
175
175
 
176
- def create_table_forms(self) -> TableData[HeaderFormsTOI]:
176
+ def create_table_forms(self) -> TableData[HeaderCartas]:
177
177
  """
178
178
  Cria uma tabela com os cabeçalhos de HeaderForms.
179
179
  """
@@ -181,12 +181,12 @@ class BuilderTablesTOI(object):
181
181
  self.default_cols_forms.for_each(lambda c: tb.add(ColumnV(c)))
182
182
  return tb
183
183
 
184
- def create_table_forms_from_df(self, df: pd.DataFrame) -> TableData[HeaderFormsTOI]:
184
+ def create_table_forms_from_df(self, df: pd.DataFrame) -> TableData[HeaderCartas]:
185
185
  df = df.astype(str)
186
186
  df_cols = ArrayList(df.columns.tolist())
187
187
  final_table = TableData()
188
188
 
189
- c: HeaderFormsTOI
189
+ c: HeaderCartas
190
190
  for c in self.default_cols_forms:
191
191
 
192
192
  if df_cols.contains(c.value):
@@ -28,7 +28,7 @@ from cartas.util import (
28
28
 
29
29
  from cartas._table_toi import (
30
30
  HeaderTOI,
31
- HeaderFormsTOI,
31
+ HeaderCartas,
32
32
  TableTOI,
33
33
  TipoCarta,
34
34
  LocalEntregaCarta,
@@ -148,7 +148,7 @@ class ControllerTOI(object):
148
148
  def load_table_toi(self) -> TableTOI:
149
149
  return self.rw.get_table_toi()
150
150
 
151
- def find_on_cache(self, data: HashMap[hashFile, File]) -> TableData[HeaderFormsTOI]:
151
+ def find_on_cache(self, data: HashMap[hashFile, File]) -> TableData[HeaderCartas]:
152
152
  """
153
153
  Procura os textos de cada arquivo na tabela OCR apartir da hash e retorna
154
154
  os dados no formato TableData()
@@ -177,24 +177,24 @@ class ControllerTOI(object):
177
177
  content = content.drop_duplicates()
178
178
 
179
179
  row_toi: RowH[HeaderTOI, Any] = content.get_row_at(0)
180
- content_row: RowH[HeaderFormsTOI, Any] = RowH(0)
180
+ content_row: RowH[HeaderCartas, Any] = RowH(0)
181
181
 
182
- content_row.set(HeaderFormsTOI.FILE_EXTENSION, f.extension() or ".nan")
183
- content_row.set(HeaderFormsTOI.FILE_BASENAME, f.basename())
184
- content_row.set(HeaderFormsTOI.IS_FILE, "S" if f.is_file() else "N")
185
- content_row.set(HeaderFormsTOI.FULL_PATH, f.absolute())
186
- content_row.set(HeaderFormsTOI.SRC, f.parent().absolute())
182
+ content_row.set(HeaderCartas.FILE_EXTENSION, f.extension() or ".nan")
183
+ content_row.set(HeaderCartas.FILE_BASENAME, f.basename())
184
+ content_row.set(HeaderCartas.IS_FILE, "S" if f.is_file() else "N")
185
+ content_row.set(HeaderCartas.FULL_PATH, f.absolute())
186
+ content_row.set(HeaderCartas.SRC, f.parent().absolute())
187
187
 
188
- content_row.set(HeaderFormsTOI.UC, row_toi.get(HeaderTOI.UC))
189
- content_row.set(HeaderFormsTOI.TOI, row_toi.get(HeaderTOI.TOI))
190
- content_row.set(HeaderFormsTOI.YEAR, row_toi.get(HeaderTOI.YEAR))
191
- content_row.set(HeaderFormsTOI.MON, row_toi.get(HeaderTOI.MON))
192
- content_row.set(HeaderFormsTOI.DAY, row_toi.get(HeaderTOI.DAY))
193
- content_row.set(HeaderFormsTOI.DATE, row_toi.get(HeaderTOI.DATE))
194
- content_row.set(HeaderFormsTOI.HASH_FILE, row_toi.get(HeaderTOI.HASH_FILE))
188
+ content_row.set(HeaderCartas.UC, row_toi.get(HeaderTOI.UC))
189
+ content_row.set(HeaderCartas.TOI, row_toi.get(HeaderTOI.TOI))
190
+ content_row.set(HeaderCartas.YEAR, row_toi.get(HeaderTOI.YEAR))
191
+ content_row.set(HeaderCartas.MON, row_toi.get(HeaderTOI.MON))
192
+ content_row.set(HeaderCartas.DAY, row_toi.get(HeaderTOI.DAY))
193
+ content_row.set(HeaderCartas.DATE, row_toi.get(HeaderTOI.DATE))
194
+ content_row.set(HeaderCartas.HASH_FILE, row_toi.get(HeaderTOI.HASH_FILE))
195
195
 
196
- content_row.set(HeaderFormsTOI.TIPO_DOC, TipoCarta.CARTA_CALCULO)
197
- content_row.set(HeaderFormsTOI.LOCAL_ENTREGA, LocalEntregaCarta.OUTRO)
196
+ content_row.set(HeaderCartas.TIPO_DOC, TipoCarta.CARTA_CALCULO)
197
+ content_row.set(HeaderCartas.LOCAL_ENTREGA, LocalEntregaCarta.OUTRO)
198
198
 
199
199
  final_tb_forms.add_row(content_row)
200
200
 
@@ -202,7 +202,7 @@ class ControllerTOI(object):
202
202
 
203
203
  def load_from_map(
204
204
  self, data_map: HashMapDict[hashFile, File], *, ignore_null: bool = True
205
- ) -> TableData[HeaderFormsTOI] | None:
205
+ ) -> TableData[HeaderCartas] | None:
206
206
  """
207
207
  I) Usa a HASH MD5 dos arquivos para buscar a data de envio do arquivo na
208
208
  tabela whatsapp;
@@ -235,7 +235,7 @@ class ControllerTOI(object):
235
235
 
236
236
  # Cada arquivo gera/extrai a sua própria tabela, ao final essa
237
237
  # lista de tabelas serão concatenadas em uma tabela única.
238
- list_tables_toi = ArrayList[TableData[HeaderFormsTOI]]()
238
+ list_tables_toi = ArrayList[TableData[HeaderCartas]]()
239
239
  header_hashs = data_map.header()
240
240
  total = header_hashs.size()
241
241
 
@@ -284,23 +284,23 @@ class ControllerTOI(object):
284
284
  year = dt.split(" ")[2]
285
285
 
286
286
  tb_toi = self.builder_toi.create_table_forms()
287
- row_forms = RowH[HeaderFormsTOI, Any](0)
288
-
289
- row_forms.set(HeaderFormsTOI.UC, uc)
290
- row_forms.set(HeaderFormsTOI.TOI, toi)
291
- row_forms.set(HeaderFormsTOI.YEAR, year)
292
- row_forms.set(HeaderFormsTOI.MON, mon)
293
- row_forms.set(HeaderFormsTOI.DAY, day)
294
- row_forms.set(HeaderFormsTOI.DATE, dt)
295
-
296
- row_forms.set(HeaderFormsTOI.FILE_EXTENSION, f.extension() or ".nan")
297
- row_forms.set(HeaderFormsTOI.FILE_BASENAME, f.basename())
298
- row_forms.set(HeaderFormsTOI.HASH_FILE, k)
299
- row_forms.set(HeaderFormsTOI.FULL_PATH, f.absolute())
300
- row_forms.set(HeaderFormsTOI.IS_FILE, "S" if f.is_file() else "N")
301
- row_forms.set(HeaderFormsTOI.SRC, f.dirname())
302
- row_forms.set(HeaderFormsTOI.TIPO_DOC, TipoCarta.CARTA_CALCULO)
303
- row_forms.set(HeaderFormsTOI.LOCAL_ENTREGA, LocalEntregaCarta.OUTRO)
287
+ row_forms = RowH[HeaderCartas, Any](0)
288
+
289
+ row_forms.set(HeaderCartas.UC, uc)
290
+ row_forms.set(HeaderCartas.TOI, toi)
291
+ row_forms.set(HeaderCartas.YEAR, year)
292
+ row_forms.set(HeaderCartas.MON, mon)
293
+ row_forms.set(HeaderCartas.DAY, day)
294
+ row_forms.set(HeaderCartas.DATE, dt)
295
+
296
+ row_forms.set(HeaderCartas.FILE_EXTENSION, f.extension() or ".nan")
297
+ row_forms.set(HeaderCartas.FILE_BASENAME, f.basename())
298
+ row_forms.set(HeaderCartas.HASH_FILE, k)
299
+ row_forms.set(HeaderCartas.FULL_PATH, f.absolute())
300
+ row_forms.set(HeaderCartas.IS_FILE, "S" if f.is_file() else "N")
301
+ row_forms.set(HeaderCartas.SRC, f.dirname())
302
+ row_forms.set(HeaderCartas.TIPO_DOC, TipoCarta.CARTA_CALCULO)
303
+ row_forms.set(HeaderCartas.LOCAL_ENTREGA, LocalEntregaCarta.OUTRO)
304
304
  tb_toi.add_row(row_forms)
305
305
  list_tables_toi.add(tb_toi)
306
306
 
@@ -8,7 +8,7 @@ from typing import Any
8
8
  import pandas as pd
9
9
 
10
10
  from table_stream import HashMapDict, ArrayList, File, TableData, RowH
11
- from cartas import HeaderFormsTOI, TipoCarta, LocalEntregaCarta
11
+ from cartas import HeaderCartas, TipoCarta, LocalEntregaCarta
12
12
 
13
13
 
14
14
  class StatusForms(StrEnum):
@@ -20,15 +20,15 @@ class StatusForms(StrEnum):
20
20
 
21
21
 
22
22
  class HeaderForms(StrEnum):
23
- UC = HeaderFormsTOI.UC
24
- TOI = HeaderFormsTOI.TOI
25
- DATA_ENTREGA = HeaderFormsTOI.DATE
23
+ UC = HeaderCartas.UC
24
+ TOI = HeaderCartas.TOI
25
+ DATA_ENTREGA = HeaderCartas.DATE
26
26
 
27
- TIPO = HeaderFormsTOI.TIPO_DOC
28
- LOCAL_ENTREGA = HeaderFormsTOI.LOCAL_ENTREGA
27
+ TIPO = HeaderCartas.TIPO_DOC
28
+ LOCAL_ENTREGA = HeaderCartas.LOCAL_ENTREGA
29
29
 
30
- HASH_FILE = HeaderFormsTOI.HASH_FILE
31
- FULL_PATH = HeaderFormsTOI.FULL_PATH
30
+ HASH_FILE = HeaderCartas.HASH_FILE
31
+ FULL_PATH = HeaderCartas.FULL_PATH
32
32
 
33
33
  STATUS = "status_forms"
34
34
  MESSAGE = "mensagem_forms"
@@ -155,37 +155,37 @@ class MapRows(HashMapDict[int, RowH[HeaderForms, Any]]):
155
155
 
156
156
  # ---- criação a partir da tabela TOI
157
157
  @staticmethod
158
- def convert_row(row_toi: RowH[HeaderFormsTOI, Any]) -> RowH[HeaderForms, Any]:
158
+ def convert_row(row_toi: RowH[HeaderCartas, Any]) -> RowH[HeaderForms, Any]:
159
159
  if row_toi.is_empty():
160
160
  raise ValueError("MapRows(): Linha TOI vazia")
161
161
 
162
- def get(h: HeaderFormsTOI, default: str = "") -> str:
162
+ def get(h: HeaderCartas, default: str = "") -> str:
163
163
  try:
164
164
  return clean_text(row_toi.get(h), default)
165
165
  except KeyError:
166
166
  return default
167
167
 
168
168
  r = RowH[HeaderForms, Any](0)
169
- r.set(HeaderForms.UC, clean_number(get(HeaderFormsTOI.UC)))
170
- r.set(HeaderForms.TOI, clean_number(get(HeaderFormsTOI.TOI)))
171
- r.set(HeaderForms.DATA_ENTREGA, get(HeaderFormsTOI.DATE))
169
+ r.set(HeaderForms.UC, clean_number(get(HeaderCartas.UC)))
170
+ r.set(HeaderForms.TOI, clean_number(get(HeaderCartas.TOI)))
171
+ r.set(HeaderForms.DATA_ENTREGA, get(HeaderCartas.DATE))
172
172
  r.set(
173
173
  HeaderForms.TIPO,
174
- get(HeaderFormsTOI.TIPO_DOC, TipoCarta.CARTA_CALCULO.value),
174
+ get(HeaderCartas.TIPO_DOC, TipoCarta.CARTA_CALCULO.value),
175
175
  )
176
176
 
177
177
  r.set(
178
178
  HeaderForms.LOCAL_ENTREGA,
179
- get(HeaderFormsTOI.LOCAL_ENTREGA, LocalEntregaCarta.OUTRO.value),
179
+ get(HeaderCartas.LOCAL_ENTREGA, LocalEntregaCarta.OUTRO.value),
180
180
  )
181
- r.set(HeaderForms.FULL_PATH, get(HeaderFormsTOI.FULL_PATH))
182
- r.set(HeaderForms.HASH_FILE, get(HeaderFormsTOI.HASH_FILE))
181
+ r.set(HeaderForms.FULL_PATH, get(HeaderCartas.FULL_PATH))
182
+ r.set(HeaderForms.HASH_FILE, get(HeaderCartas.HASH_FILE))
183
183
  r.set(HeaderForms.STATUS, StatusForms.PENDING)
184
184
  r.set(HeaderForms.MESSAGE, "")
185
185
  return r
186
186
 
187
187
  @classmethod
188
- def create_from_table(cls, tb: TableData[HeaderFormsTOI]) -> MapRows:
188
+ def create_from_table(cls, tb: TableData[HeaderCartas]) -> MapRows:
189
189
  mp = cls()
190
190
  for n in range(tb.size()):
191
191
  mp.set_value(n, cls.convert_row(tb.get_row_at(n)))
@@ -12,7 +12,7 @@ from converter.config_app import AppConfigNotifier
12
12
  from converter.page_forms.common import MapRows, StatusForms
13
13
  from converter.page_forms.model_forms import ModelForms, FormsCallbacks
14
14
 
15
- from cartas import HeaderFormsTOI, BuilderTablesTOI
15
+ from cartas import HeaderCartas, BuilderTablesTOI
16
16
  from table_stream import File, Directory, TableData
17
17
 
18
18
 
@@ -30,7 +30,7 @@ class ControllerForms(ChangeNotifier):
30
30
  super().__init__()
31
31
  self.model: ModelForms = model
32
32
  self.map_rows = MapRows()
33
- self.table_toi: TableData[HeaderFormsTOI] = TableData()
33
+ self.table_toi: TableData[HeaderCartas] = TableData()
34
34
  self.selected_table_file: File | None = None
35
35
 
36
36
  self.status_text: str = "Importe uma tabela TOI para começar."
@@ -76,7 +76,7 @@ class ControllerForms(ChangeNotifier):
76
76
  self.status_text = f"{mp.size_header()} cartas importadas. Pronto para lançar."
77
77
  self.notify_listeners()
78
78
 
79
- def set_table_toi(self, tb: TableData[HeaderFormsTOI]) -> None:
79
+ def set_table_toi(self, tb: TableData[HeaderCartas]) -> None:
80
80
  if tb.is_empty():
81
81
  self.show_error("Tabela TOI vazia")
82
82
  return
@@ -84,10 +84,10 @@ class ControllerForms(ChangeNotifier):
84
84
  missing = [
85
85
  h.value
86
86
  for h in (
87
- HeaderFormsTOI.UC,
88
- HeaderFormsTOI.TOI,
89
- HeaderFormsTOI.DATE,
90
- HeaderFormsTOI.FULL_PATH,
87
+ HeaderCartas.UC,
88
+ HeaderCartas.TOI,
89
+ HeaderCartas.DATE,
90
+ HeaderCartas.FULL_PATH,
91
91
  )
92
92
  if not tb.header().contains(h)
93
93
  ]
@@ -32,6 +32,7 @@ from table_stream import (
32
32
  ListTablesEmptyError,
33
33
  ColumnNotFoundError,
34
34
  load_file_hash,
35
+ SequenceTables,
35
36
  )
36
37
 
37
38
 
@@ -147,14 +148,17 @@ class TableOcr(TableData[HeaderOcr]):
147
148
  @classmethod
148
149
  def create_from_data(cls, data: pd.DataFrame) -> TableOcr:
149
150
  df_columns = ArrayList(data.columns.tolist())
151
+ header_ocr = ArrayList[HeaderOcr].from_list(list(HeaderOcr))
150
152
  tb = cls()
151
153
 
152
- for c in HeaderOcr:
154
+ c: HeaderOcr
155
+ for c in header_ocr:
156
+
153
157
  if df_columns.contains(c.value):
154
158
  tb.add(
155
- ColumnV(
159
+ ColumnV[HeaderOcr, Any].create_from_list(
156
160
  c,
157
- ArrayList(data[c.value].astype("str").values.tolist()),
161
+ data[c.value].astype("str").values.tolist(),
158
162
  )
159
163
  )
160
164
 
@@ -201,6 +205,7 @@ class ReadWriteTableOCR(object):
201
205
 
202
206
  self._table_image: TableOcr = None
203
207
  self._table_pdf: TableOcr = None
208
+ self.default_cols = BuilderTableOcr().default_basic_header_ocr
204
209
 
205
210
  @property
206
211
  def file_table_image(self) -> File:
@@ -283,47 +288,72 @@ class ReadWriteTableOCR(object):
283
288
  if new.is_empty():
284
289
  return None
285
290
 
291
+ df_new = new.select_columns(self.default_cols).to_dataframe()
292
+ df_new = df_new.drop_duplicates(subset=[HeaderOcr.ID]).dropna(
293
+ subset=[HeaderOcr.TEXT]
294
+ )
295
+
286
296
  df_pdf = self.load_table_pdf().to_dataframe()
287
- df_new = new.to_dataframe()
288
- final_list = list()
289
297
 
290
- if not df_pdf.empty:
291
- final_list.append(df_pdf)
292
- if not df_new.empty:
293
- final_list.append(df_new)
298
+ final_list = SequenceTables[TableOcr]()
299
+ final_list.add(TableOcr.create_from_data(df_pdf))
300
+ final_list.add(TableOcr.create_from_data(df_new))
294
301
 
295
- if len(final_list) == 0:
302
+ if final_list.empty():
296
303
  return None
297
304
 
298
- df: pd.DataFrame = pd.concat(final_list)
299
- df.drop_duplicates()
300
- self._table_pdf = self.create_table_from_data(df)
305
+ self._table_pdf = final_list.concat(TableOcr)
301
306
  self.save_table_pdf(self._table_pdf)
302
307
 
303
308
  def merge_table_image(self, new: TableOcr) -> None:
304
309
  if new.is_empty():
305
310
  return None
306
311
 
307
- df_image = self.load_table_image().to_dataframe()
308
- df_new = new.to_dataframe()
309
- final_list = list()
312
+ df_new = new.select_columns(self.default_cols).to_dataframe()
313
+ df_new = df_new.drop_duplicates(subset=[HeaderOcr.ID]).dropna(
314
+ subset=[HeaderOcr.TEXT]
315
+ )
310
316
 
311
- if not df_image.empty:
312
- final_list.append(df_image)
313
- if not df_new.empty:
314
- final_list.append(df_new)
317
+ df_imgs = self.load_table_image().to_dataframe()
318
+ df_imgs = df_imgs.dropna(
319
+ subset=[HeaderOcr.TEXT]
320
+ ) # .drop_duplicates(subset=[HeaderOcr.ID])
315
321
 
316
- if len(final_list) == 0:
317
- return None
322
+ sequence_imgs = SequenceTables[TableOcr]()
323
+ sequence_imgs.add(TableOcr.create_from_data(df_imgs))
324
+ sequence_imgs.add(TableOcr.create_from_data(df_new))
318
325
 
319
- df: pd.DataFrame = pd.concat(final_list)
320
- df.drop_duplicates()
321
- self._table_image = self.create_table_from_data(df)
322
- self.save_table_image(self._table_pdf)
326
+ self._table_image: TableOcr = sequence_imgs.concat(TableOcr)
327
+ self.save_table_image(self._table_image)
323
328
 
324
329
 
325
330
  def concat_tables_ocr(values: list[TableOcr]) -> TableOcr:
326
- return concat_tables(values, rt_type=TableOcr)
331
+
332
+ if len(values) == 0:
333
+ raise ListTablesEmptyError("Não é possível concatenar uma lista vazia!")
334
+
335
+ header = values[0].header()
336
+ total_cols = header.size()
337
+
338
+ final: TableOcr = TableOcr()
339
+ header.for_each(lambda h: final.add(ColumnV(h)))
340
+
341
+ current_table: TableOcr
342
+
343
+ for n, current_table in enumerate(values):
344
+ if current_table.is_empty():
345
+ raise TableEmptyError(
346
+ f"concat_tables_ocr: A tabela {n+1} da lista está vazia ... Não é possível concatenar!"
347
+ )
348
+
349
+ if current_table.size_header() != total_cols:
350
+ msg = f"concat_tables_ocr: a tabela {n+1} tem cabeçalho diferente a primeira tabela"
351
+ msg2 = f"Tabela 1: {total_cols} Colunas | Tabela {n+1}: {current_table.size_header()} Colunas"
352
+ raise HeadersSizeNotIqualError(f"{msg}\n\n{msg2}\n")
353
+
354
+ final.merge(current_table)
355
+
356
+ return final
327
357
 
328
358
 
329
359
  def increment_columns_ocr(tb: TableOcr, f: File) -> TableOcr:
@@ -332,29 +362,44 @@ def increment_columns_ocr(tb: TableOcr, f: File) -> TableOcr:
332
362
  HeaderOcr.FILENAME, HeaderOcr.FILE_EXTENSION, HeaderOcr.FILE_BASENAME e HeaderOcr.FILE_PATH
333
363
  """
334
364
 
335
- total = tb.size()
336
- if total == 0:
365
+ if tb.is_void():
337
366
  raise TableEmptyError(
338
367
  f"Não é possível complementar colunas OCR em uma tabela vazia. Adicione informações a tabela para prosseguir!"
339
368
  )
340
369
 
341
370
  hashes = tb.get(HeaderOcr.HASH_FILE).drop_duplicates()
371
+
342
372
  if hashes.size() > 1:
343
373
  raise ValueError(
344
374
  "A tabela atual possui hash de mais de um arquivo, essa operação só permite a adição de"
345
375
  "colunas para uma tabela que repesenta apenas um arquivo."
346
376
  )
347
377
 
348
- tb.set(ColumnV.create_from_list(HeaderOcr.FILENAME, [f.name()] * total))
349
- tb.set(ColumnV.create_from_list(HeaderOcr.FILE_EXTENSION, [f.extension()] * total))
350
- tb.set(ColumnV.create_from_list(HeaderOcr.FILE_BASENAME, [f.basename()] * total))
351
- tb.set(ColumnV.create_from_list(HeaderOcr.FILE_PATH, [f.absolute()] * total))
378
+ total = tb.size()
379
+
380
+ if total == 0:
381
+ tb.set(ColumnV.create_from_list(HeaderOcr.FILENAME, [f.name()]))
382
+ tb.set(ColumnV.create_from_list(HeaderOcr.FILE_EXTENSION, [f.extension()]))
383
+ tb.set(ColumnV.create_from_list(HeaderOcr.FILE_BASENAME, [f.basename()]))
384
+ tb.set(ColumnV.create_from_list(HeaderOcr.FILE_PATH, [f.absolute()]))
385
+ else:
386
+ tb.set(ColumnV.create_from_list(HeaderOcr.FILENAME, [f.name()] * total))
387
+ tb.set(
388
+ ColumnV.create_from_list(HeaderOcr.FILE_EXTENSION, [f.extension()] * total)
389
+ )
390
+ tb.set(
391
+ ColumnV.create_from_list(HeaderOcr.FILE_BASENAME, [f.basename()] * total)
392
+ )
393
+ tb.set(ColumnV.create_from_list(HeaderOcr.FILE_PATH, [f.absolute()] * total))
394
+
352
395
  return tb
353
396
 
354
397
 
355
398
  # ==================================================================#
356
399
  # Adicionar configurações globais diretórios, arquivos e etc.
357
400
  # ==================================================================#
401
+
402
+
358
403
  class BuilderTableOcr(object):
359
404
  """
360
405
  classe para criar objetos TableOcr() personalizados, se você
@@ -363,7 +408,7 @@ class BuilderTableOcr(object):
363
408
 
364
409
  def __init__(self) -> None:
365
410
  # Ordem em que o cabeçalho deve ser criado.
366
- self.default_all_header_ocr: ArrayList = ArrayList.from_list(
411
+ self.default_all_header_ocr = ArrayList[HeaderOcr].from_list(
367
412
  [
368
413
  HeaderOcr.ID,
369
414
  HeaderOcr.HASH_FILE,
@@ -379,7 +424,7 @@ class BuilderTableOcr(object):
379
424
 
380
425
  # Colunas para guardar informações básicas dos textos OCR sem
381
426
  # informações do arquivo, excerto a HASH.
382
- self.default_basic_header_ocr: ArrayList = ArrayList.from_list(
427
+ self.default_basic_header_ocr = ArrayList[HeaderOcr].from_list(
383
428
  [
384
429
  HeaderOcr.ID,
385
430
  HeaderOcr.HASH_FILE,
@@ -389,6 +434,9 @@ class BuilderTableOcr(object):
389
434
  ]
390
435
  )
391
436
 
437
+ def contains_all_header_ocr(self, tb: TableOcr) -> bool:
438
+ return tb.size_header() == self.default_all_header_ocr.size()
439
+
392
440
  def create_with_full_header(self) -> TableOcr:
393
441
  """
394
442
  Cria uma tabela OCR vazia com todas as colunas de HeaderOcr.