luxorasap 0.2.12__py3-none-any.whl → 0.2.14__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.
luxorasap/__init__.py CHANGED
@@ -13,7 +13,7 @@ from types import ModuleType
13
13
  try:
14
14
  __version__: str = metadata.version(__name__)
15
15
  except metadata.PackageNotFoundError: # editable install
16
- __version__ = "0.2.12"
16
+ __version__ = "0.2.14"
17
17
 
18
18
  # ─── Lazy loader ─────────────────────────────────────────────────
19
19
  def __getattr__(name: str) -> ModuleType:
@@ -60,6 +60,13 @@ def save_table(
60
60
  if index:
61
61
  df = df.reset_index().rename(columns={"index": index_name})
62
62
  _client_excel.write_excel(df, f"{directory}/{table_name}.xlsx")
63
+
64
+ elif format == 'excel_multiple_sheets':
65
+ global _client_excel
66
+ if _client_excel is None:
67
+ _client_excel = BlobExcelClient()
68
+ # df neste caso é um dicionário de DataFrames
69
+ _client_excel.write_excel_multiple_sheets(df, f"{directory}/{table_name}.xlsx")
63
70
 
64
71
  elif format == 'pickle':
65
72
  global _client_pickle
@@ -157,6 +157,51 @@ class BlobExcelClient:
157
157
  self._container.upload_blob(name=blob_name, data=buf, overwrite=True)
158
158
 
159
159
 
160
+ def write_excel_multiple_sheets(
161
+ self,
162
+ sheets: dict[str, pd.DataFrame],
163
+ blob_name: str,
164
+ *,
165
+ index: bool = False,
166
+ engine: str = "openpyxl",
167
+ **to_excel_kwargs,
168
+ ) -> None:
169
+ """
170
+ Salva várias abas de uma planilha Excel no blob, a partir de um dicionário
171
+ {nome_aba: DataFrame}.
172
+
173
+ Args:
174
+ sheets: Mapa de nome da aba -> DataFrame.
175
+ blob_name: Caminho/nome do blob (ex.: "reports/minha_planilha.xlsx").
176
+ index: Se True, escreve o índice dos DataFrames.
177
+ engine: Engine do pandas.ExcelWriter (default "openpyxl").
178
+ **to_excel_kwargs: repassado a `DataFrame.to_excel` (ex.: na_format, float_format).
179
+ """
180
+
181
+ def _sanitize_sheet_name(name: str) -> str:
182
+ # Excel limita a 31 chars e proíbe alguns caracteres
183
+ s = str(name)[:31]
184
+ for ch, repl in {":": "_", "/": "_", "\\": "_", "?": "_", "*": "_", "[": "(", "]": ")"}.items():
185
+ s = s.replace(ch, repl)
186
+ return s
187
+
188
+ if not isinstance(sheets, dict) or not sheets:
189
+ raise ValueError("`sheets` deve ser um dicionário não vazio 'aba': 'DataFrame'.")
190
+
191
+ buf = io.BytesIO()
192
+ with pd.ExcelWriter(buf, engine=engine) as writer:
193
+ for sheet_name, df in sheets.items():
194
+ sanitized = _sanitize_sheet_name(sheet_name)
195
+ if not isinstance(df, pd.DataFrame):
196
+ # tenta converter objetos "tabelares" em DataFrame
197
+ df = pd.DataFrame(df)
198
+ df.to_excel(writer, sheet_name=sanitized, index=index, **to_excel_kwargs)
199
+
200
+ buf.seek(0)
201
+ self._container.upload_blob(name=blob_name, data=buf, overwrite=True)
202
+
203
+
204
+
160
205
  def read_excel(self, blob_name: str, **kwargs) -> pd.DataFrame:
161
206
  """
162
207
  Lê um arquivo Excel do blob e retorna um DataFrame.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: luxorasap
3
- Version: 0.2.12
3
+ Version: 0.2.14
4
4
  Summary: Toolbox da Luxor para ingestão, análise e automação de dados financeiros.
5
5
  Author-email: Luxor Group <backoffice@luxor.com.br>
6
6
  License: Proprietary – All rights reserved
@@ -1,4 +1,4 @@
1
- luxorasap/__init__.py,sha256=qmCFLnriRBLL3UlKCDNcng-JHSehVikZtOteu-NME5U,1356
1
+ luxorasap/__init__.py,sha256=xDbLsrCmxU8ikmmC0bupvVN_t_PEOd9NrREMfq9AH9I,1356
2
2
  luxorasap/btgapi/__init__.py,sha256=QUlfb5oiBY6K1Q5x4-a-x2wECe1At5wc2962I5odOJk,620
3
3
  luxorasap/btgapi/auth.py,sha256=PvyCtbEyBO2B1CIeAlNXWugKW1OgiKfPcVzS6K5FBnQ,1872
4
4
  luxorasap/btgapi/reports.py,sha256=ZVEMLoJPXc0r3XjPJPMsKQN0zZd1Npd7umNpAj1bncs,8040
@@ -6,19 +6,19 @@ luxorasap/btgapi/trades.py,sha256=956HZ9BvN9C_VQvKTyBLN0x6ZygwVqBZN11F7OnNbDI,59
6
6
  luxorasap/datareader/__init__.py,sha256=41RAvbrQ4R6oj67S32CrKqolx0CJ2W8cbOF6g5Cqm2g,120
7
7
  luxorasap/datareader/core.py,sha256=D7nNdKiu5VAii4xWnoqO1PR0qaYi3YEfKyxhkVGZ1j8,158784
8
8
  luxorasap/ingest/__init__.py,sha256=gHkw8FU8TuRL5tfHkACxwsLHwLYX8SgX9xHkB8uTjww,831
9
- luxorasap/ingest/cloud/__init__.py,sha256=I0JZh9FbGnIVxu7VmiTXe8rKN_w5OWLULvkVkVZNeUk,7242
9
+ luxorasap/ingest/cloud/__init__.py,sha256=zoepoVcXNFtVj62aUyqu9AY7u6vX0RIKRWDfXOn2J4Q,7548
10
10
  luxorasap/ingest/legacy_local/dataloader.py,sha256=DF3CvojDAi0itVDZPsQbmpl5pqMTNwOOpxTz4Ju8mho,12419
11
11
  luxorasap/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  luxorasap/utils/dataframe/__init__.py,sha256=heKpmq58FmX35syzzwrHqlOWKYBkH2Z1jyqaQ_Vg-00,265
13
13
  luxorasap/utils/dataframe/reader.py,sha256=Vzjdw-AeS1lnWEHQ8RZNh0kK93NWTp0NWVi_B6mN5N0,616
14
14
  luxorasap/utils/dataframe/transforms.py,sha256=OIvlTTcjFX6bUhuQp_syEp7ssm4sLzwvgsag6n2Wl3k,2438
15
15
  luxorasap/utils/storage/__init__.py,sha256=461GYJcPMXGjHuJ9y9D3BHOC_oUS9Re32nVu1AwKyIA,334
16
- luxorasap/utils/storage/blob.py,sha256=vgCKMOiVgP-V1A2xZRhG3kJhPFU-LA9E9kddOQTxYD8,9443
16
+ luxorasap/utils/storage/blob.py,sha256=28bsUbEUjg_LapDZ4P3kWkxHDQGNXv_Jik49RfXbwME,11223
17
17
  luxorasap/utils/storage/change_tracker.py,sha256=HkeKc62UyD2BtP2gqafnJHZSBvYreH_7SQI1CYhn3Us,11709
18
18
  luxorasap/utils/tools/__init__.py,sha256=dvK7Z4xnNQAuEiObVN7qjeLWAvP49JeFn2Oq9GdgmXs,76
19
19
  luxorasap/utils/tools/excel.py,sha256=SfeTcbJWsWq3uKruwKSjJ4aWgMovITzlNXjP2bhdMjI,1246
20
- luxorasap-0.2.12.dist-info/METADATA,sha256=NfuDMRUJjqpXvliK93mzJicsmHNrsdnidGVPQOW1zeA,3804
21
- luxorasap-0.2.12.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
22
- luxorasap-0.2.12.dist-info/entry_points.txt,sha256=XFh-dOwUhlya9DmGvgookMI0ezyUJjcOvTIHDEYS44g,52
23
- luxorasap-0.2.12.dist-info/top_level.txt,sha256=9YOL6bUIpzY06XFBRkUW1e4rgB32Ds91fQPGwUEjxzU,10
24
- luxorasap-0.2.12.dist-info/RECORD,,
20
+ luxorasap-0.2.14.dist-info/METADATA,sha256=smLlV2FPeq9rNwPCAgNb2AYfy6tPqMLlKlE78kJUoaw,3804
21
+ luxorasap-0.2.14.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
22
+ luxorasap-0.2.14.dist-info/entry_points.txt,sha256=XFh-dOwUhlya9DmGvgookMI0ezyUJjcOvTIHDEYS44g,52
23
+ luxorasap-0.2.14.dist-info/top_level.txt,sha256=9YOL6bUIpzY06XFBRkUW1e4rgB32Ds91fQPGwUEjxzU,10
24
+ luxorasap-0.2.14.dist-info/RECORD,,