luxorasap 0.1.18__tar.gz → 0.1.19__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.
- {luxorasap-0.1.18 → luxorasap-0.1.19}/PKG-INFO +1 -1
- {luxorasap-0.1.18 → luxorasap-0.1.19}/pyproject.toml +2 -2
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/__init__.py +1 -1
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/ingest/cloud/__init__.py +2 -1
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/utils/dataframe/__init__.py +1 -1
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/utils/dataframe/transforms.py +19 -1
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/utils/storage/blob.py +1 -1
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap.egg-info/PKG-INFO +1 -1
- {luxorasap-0.1.18 → luxorasap-0.1.19}/tests/test_ingest_cloud.py +1 -1
- {luxorasap-0.1.18 → luxorasap-0.1.19}/README.md +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/setup.cfg +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/btgapi/__init__.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/btgapi/auth.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/btgapi/reports.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/btgapi/trades.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/datareader/__init__.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/datareader/core.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/ingest/__init__.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/ingest/legacy_local/dataloader.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/utils/__init__.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/utils/dataframe/reader.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap/utils/storage/__init__.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap.egg-info/SOURCES.txt +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap.egg-info/dependency_links.txt +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap.egg-info/entry_points.txt +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap.egg-info/requires.txt +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/src/luxorasap.egg-info/top_level.txt +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/tests/test_btgapi_auth.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/tests/test_btgapi_reports.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/tests/test_btgapi_trades.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/tests/test_datareader.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/tests/test_ingest_legacy_local.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/tests/test_utils_dataframe.py +0 -0
- {luxorasap-0.1.18 → luxorasap-0.1.19}/tests/test_utils_storage.py +0 -0
|
@@ -10,7 +10,7 @@ build-backend = "setuptools.build_meta"
|
|
|
10
10
|
#############################
|
|
11
11
|
[project]
|
|
12
12
|
name = "luxorasap"
|
|
13
|
-
version = "0.1.
|
|
13
|
+
version = "0.1.19"
|
|
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.
|
|
81
|
+
current_version = "0.1.19"
|
|
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.
|
|
16
|
+
__version__ = "0.1.19"
|
|
17
17
|
|
|
18
18
|
# ─── Lazy loader ─────────────────────────────────────────────────
|
|
19
19
|
def __getattr__(name: str) -> ModuleType:
|
|
@@ -4,7 +4,7 @@ import pandas as pd
|
|
|
4
4
|
import datetime as dt
|
|
5
5
|
|
|
6
6
|
from luxorasap.utils.storage import BlobParquetClient
|
|
7
|
-
from luxorasap.utils.dataframe import prep_for_save
|
|
7
|
+
from luxorasap.utils.dataframe import prep_for_save, astype_str_inplace
|
|
8
8
|
from luxorasap.datareader import LuxorQuery
|
|
9
9
|
|
|
10
10
|
|
|
@@ -37,6 +37,7 @@ def save_table(
|
|
|
37
37
|
df = prep_for_save(df, index=index, index_name=index_name, normalize=normalize_columns)
|
|
38
38
|
|
|
39
39
|
#_client.write_df(df.astype(str), f"{directory}/{table_name}.parquet")
|
|
40
|
+
astype_str_inplace(df)
|
|
40
41
|
_client.write_df(df, f"{directory}/{table_name}.parquet")
|
|
41
42
|
|
|
42
43
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
from .transforms import prep_for_save, persist_column_formatting, text_to_lowercase_inplace
|
|
2
2
|
from .reader import read_bytes
|
|
3
3
|
|
|
4
|
-
__all__ = ["prep_for_save", "persist_column_formatting", "text_to_lowercase_inplace", "read_bytes"]
|
|
4
|
+
__all__ = ["prep_for_save", "persist_column_formatting", "text_to_lowercase_inplace", "read_bytes", "astype_str_inplace"]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import pandas as pd
|
|
2
|
+
import gc
|
|
2
3
|
from pandas.api.types import is_object_dtype, is_string_dtype
|
|
3
4
|
|
|
4
5
|
|
|
@@ -55,4 +56,21 @@ def prep_for_save(
|
|
|
55
56
|
if index:
|
|
56
57
|
name = df.index.name or index_name
|
|
57
58
|
df = df.reset_index().rename(columns={"index": name})
|
|
58
|
-
return persist_column_formatting(df) if normalize else df
|
|
59
|
+
return persist_column_formatting(df) if normalize else df
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def astype_str_inplace(df: pd.DataFrame, *, gc_every: int = 3) -> None:
|
|
63
|
+
"""
|
|
64
|
+
Converte TODAS as colunas para string sem duplicar o DataFrame completo.
|
|
65
|
+
Em cada passo:
|
|
66
|
+
• cria uma nova Series (coluna convertida)
|
|
67
|
+
• substitui a antiga
|
|
68
|
+
• libera memória da coluna anterior
|
|
69
|
+
Isso mantém o pico de RAM ≤ tamanho da maior coluna.
|
|
70
|
+
"""
|
|
71
|
+
for i, col in enumerate(df.columns):
|
|
72
|
+
df[col] = df[col].astype(str)
|
|
73
|
+
|
|
74
|
+
# opcional: força coleta de lixo a cada N colunas
|
|
75
|
+
if (i + 1) % gc_every == 0:
|
|
76
|
+
gc.collect()
|
|
@@ -37,7 +37,7 @@ class BlobParquetClient:
|
|
|
37
37
|
def write_df(self, df, blob_path: str):
|
|
38
38
|
|
|
39
39
|
blob = self._blob(blob_path)
|
|
40
|
-
table = pa.Table.from_pandas(df
|
|
40
|
+
table = pa.Table.from_pandas(df)
|
|
41
41
|
buf = io.BytesIO()
|
|
42
42
|
pq.write_table(table, buf)
|
|
43
43
|
buf.seek(0)
|
|
@@ -16,7 +16,7 @@ def test_save_table_calls_blob_client(fake_blob, monkeypatch):
|
|
|
16
16
|
df = pd.DataFrame({"x": [1]})
|
|
17
17
|
cloud.save_table("t1", df, directory="dir")
|
|
18
18
|
assert captured["path"] == "dir/t1.parquet"
|
|
19
|
-
assert captured["df"].equals(df)
|
|
19
|
+
assert captured["df"].equals(df.astype(str))
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def test_incremental_load_merges_correctly(fake_blob, monkeypatch):
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|