luxorasap 0.1.36__tar.gz → 0.1.38__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 (37) hide show
  1. {luxorasap-0.1.36 → luxorasap-0.1.38}/PKG-INFO +1 -1
  2. {luxorasap-0.1.36 → luxorasap-0.1.38}/pyproject.toml +2 -2
  3. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/__init__.py +1 -1
  4. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/datareader/core.py +16 -5
  5. luxorasap-0.1.38/src/luxorasap/utils/storage/__init__.py +2 -0
  6. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/utils/storage/blob.py +29 -1
  7. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap.egg-info/PKG-INFO +1 -1
  8. luxorasap-0.1.36/src/luxorasap/utils/storage/__init__.py +0 -2
  9. {luxorasap-0.1.36 → luxorasap-0.1.38}/README.md +0 -0
  10. {luxorasap-0.1.36 → luxorasap-0.1.38}/setup.cfg +0 -0
  11. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/btgapi/__init__.py +0 -0
  12. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/btgapi/auth.py +0 -0
  13. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/btgapi/reports.py +0 -0
  14. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/btgapi/trades.py +0 -0
  15. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/datareader/__init__.py +0 -0
  16. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/ingest/__init__.py +0 -0
  17. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/ingest/cloud/__init__.py +0 -0
  18. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/ingest/legacy_local/dataloader.py +0 -0
  19. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/utils/__init__.py +0 -0
  20. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/utils/dataframe/__init__.py +0 -0
  21. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/utils/dataframe/reader.py +0 -0
  22. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/utils/dataframe/transforms.py +0 -0
  23. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/utils/tools/__init__.py +0 -0
  24. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap/utils/tools/excel.py +0 -0
  25. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap.egg-info/SOURCES.txt +0 -0
  26. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap.egg-info/dependency_links.txt +0 -0
  27. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap.egg-info/entry_points.txt +0 -0
  28. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap.egg-info/requires.txt +0 -0
  29. {luxorasap-0.1.36 → luxorasap-0.1.38}/src/luxorasap.egg-info/top_level.txt +0 -0
  30. {luxorasap-0.1.36 → luxorasap-0.1.38}/tests/test_btgapi_auth.py +0 -0
  31. {luxorasap-0.1.36 → luxorasap-0.1.38}/tests/test_btgapi_reports.py +0 -0
  32. {luxorasap-0.1.36 → luxorasap-0.1.38}/tests/test_btgapi_trades.py +0 -0
  33. {luxorasap-0.1.36 → luxorasap-0.1.38}/tests/test_datareader.py +0 -0
  34. {luxorasap-0.1.36 → luxorasap-0.1.38}/tests/test_ingest_cloud.py +0 -0
  35. {luxorasap-0.1.36 → luxorasap-0.1.38}/tests/test_ingest_legacy_local.py +0 -0
  36. {luxorasap-0.1.36 → luxorasap-0.1.38}/tests/test_utils_dataframe.py +0 -0
  37. {luxorasap-0.1.36 → luxorasap-0.1.38}/tests/test_utils_storage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: luxorasap
3
- Version: 0.1.36
3
+ Version: 0.1.38
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
@@ -10,7 +10,7 @@ build-backend = "setuptools.build_meta"
10
10
  #############################
11
11
  [project]
12
12
  name = "luxorasap"
13
- version = "0.1.36"
13
+ version = "0.1.38"
14
14
  description = "Toolbox da Luxor para ingestão, análise e automação de dados financeiros."
15
15
  readme = "README.md"
16
16
  requires-python = ">=3.9"
@@ -78,7 +78,7 @@ exclude = ["tests*"]
78
78
  # bumpver (sem-ver)
79
79
  #############################
80
80
  [tool.bumpver]
81
- current_version = "0.1.36"
81
+ current_version = "0.1.38"
82
82
  version_pattern = "MAJOR.MINOR.PATCH"
83
83
 
84
84
  # regex explícito – obrigatório no bumpver 2024+
@@ -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.1.36"
16
+ __version__ = "0.1.38"
17
17
 
18
18
  # ─── Lazy loader ─────────────────────────────────────────────────
19
19
  def __getattr__(name: str) -> ModuleType:
@@ -101,6 +101,13 @@ class LuxorQuery:
101
101
  return self.blob_client.table_exists(table_path)
102
102
 
103
103
 
104
+ def list_tables(self):
105
+ """Lista todas as tabelas disponiveis no blob"""
106
+ tables = self.blob_client.list_blob_files(self.blob_directory, ends_with=".parquet")
107
+ tables = [os.path.basename(t).replace(".parquet","") for t in tables]
108
+ return tables
109
+
110
+
104
111
  def get_table(self, table_name, index=False, index_name="index", dtypes_override={}, force_reload=False):
105
112
  """
106
113
  Retorna uma copia do DataFrame do 'table_name' correspondente. Se não estiver disponivel,
@@ -187,7 +194,7 @@ class LuxorQuery:
187
194
  for col in table_columns.intersection(float_dtypes):
188
195
  table_data[col] = table_data[col].astype(float)
189
196
  except :
190
- logger.warning(f"Ao carregar tabela '{table_name}', nao foi possivel converter dados da coluna {col} para float.")
197
+ logger.error(f"Ao carregar tabela '{table_name}', nao foi possivel converter dados da coluna {col} para float.")
191
198
  #logger.warning(f"Colunas com erro: {table_columns.intersection(float_dtypes)}")
192
199
  #logger.warning(f"Colunas disponiveis: {table_columns}")
193
200
  #print(table_data.dtypes)
@@ -209,10 +216,14 @@ class LuxorQuery:
209
216
  table_data[col] = table_data[col].apply(lambda x: pd.to_datetime(x))
210
217
 
211
218
  for col in table_columns.intersection(bool_dtypes):
212
- table_data[col] = (table_data[col].str.lower()
213
- .replace("false", "").replace("falso", "")
214
- .replace("0", "").replace("nan", "").astype(bool))
215
-
219
+ try:
220
+ table_data[col] = (table_data[col].str.lower()
221
+ .replace("false", "").replace("falso", "")
222
+ .replace("0", "").replace("nan", "").astype(bool))
223
+ except Exception:
224
+ logger.error(f"Ao carregar tabela '{table_name}', nao foi possivel converter dados da coluna {col} para bool.")
225
+ raise ValueError(f"Erro ao converter coluna {col} para bool na tabela '{table_name}'.")
226
+
216
227
  for col in table_columns.intersection(str_nan_format):
217
228
  table_data[col] = table_data[col].replace("nan", pd.NA).replace("", pd.NA)
218
229
 
@@ -0,0 +1,2 @@
1
+ from .blob import BlobParquetClient, BlobPickleClient
2
+ __all__ = ["BlobParquetClient", "BlobPickleClient"]
@@ -4,7 +4,7 @@ from datetime import timezone
4
4
  import pandas as pd
5
5
  import pyarrow as pa, pyarrow.parquet as pq
6
6
  from azure.storage.blob import BlobServiceClient
7
- import io
7
+ import pickle
8
8
 
9
9
  from ..dataframe import read_bytes
10
10
 
@@ -93,4 +93,32 @@ class BlobParquetClient:
93
93
  def _blob(self, path: str):
94
94
  path = str(PurePosixPath(path))
95
95
  return self._svc.get_blob_client(self._container, path)
96
+
97
+
98
+ class BlobPickleClient:
99
+ def __init__(self, *, adls_connection_string: str = None, container: str = "luxorasap"):
100
+ if adls_connection_string is None:
101
+ adls_connection_string = os.getenv("AZURE_STORAGE_CONNECTION_STRING")
102
+
103
+ if adls_connection_string is None:
104
+ raise RuntimeError("AZURE_STORAGE_CONNECTION_STRING not set")
105
+
106
+ self.blob_service_client = BlobServiceClient.from_connection_string(adls_connection_string)
107
+ self.container_client = self.blob_service_client.get_container_client(container)
108
+
109
+ def write_pickle(self, obj, blob_name: str):
110
+ """Salva objeto Python (ex: DataFrame) como pickle no blob"""
111
+ buf = io.BytesIO()
112
+ pickle.dump(obj, buf)
113
+ buf.seek(0)
114
+ self.container_client.upload_blob(name=blob_name, data=buf, overwrite=True)
115
+
116
+ def read_pickle(self, blob_name: str):
117
+ """Lê pickle do blob e retorna objeto Python"""
118
+ downloader = self.container_client.download_blob(blob_name)
119
+ buf = io.BytesIO(downloader.readall())
120
+ return pickle.load(buf)
121
+
122
+ def exists(self, blob_name: str) -> bool:
123
+ return self.container_client.get_blob_client(blob_name).exists()
96
124
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: luxorasap
3
- Version: 0.1.36
3
+ Version: 0.1.38
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,2 +0,0 @@
1
- from .blob import BlobParquetClient
2
- __all__ = ["BlobParquetClient"]
File without changes
File without changes