mtcli 3.8.0.dev13__tar.gz → 3.8.0.dev14__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.
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/PKG-INFO +1 -1
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/runner.py +65 -9
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/pyproject.toml +1 -1
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/LICENSE +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/README.md +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/__main__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/cli.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/cli_dev.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands/backfill.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands/bars.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands/conf.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands/doctor.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands/ticks.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands_dev/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands_dev/migrate.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/conecta.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/conf.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/config_registre.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/data/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/data/base.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/data/csv.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/data/mt5.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/database.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/domain/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/domain/timeframe.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/logger.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/backfill_engine.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/tick_bus.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/tick_cache.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/tick_engine.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/tick_repository.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/tick_writer.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/001_initial_schema.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/002_ticks_time_msc.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/003_optimize_ticks_without_rowid.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/004_ticks_pk_time_msc.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/005_tick_price_compression.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/006_add_index_ticks_symbol_time.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/007_deduplicate_ticks_and_add_unique_index.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/__main__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/bar_model.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/bars_model.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/chart_model.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/conf_model.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/consecutive_bars_model.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/rates_model.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/signals_model.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/unconsecutive_bar_model.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/mt5_context.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugin.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugin_loader.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugin_manager.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/exemplo.py-dist +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/cli.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/conf.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/models/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/models/model_media_movel.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/tests/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/tests/test_mm.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/tests/test_model_media_movel.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/cli.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/conf.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/models/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/models/average_range_model.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/tests/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/tests/test_rm.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/cli.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/conf.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/models/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/models/model_average_volume.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/tests/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/tests/test_vm.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/services/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/services/maintenance_service.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/services/tick_service.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/__init__.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/close_view.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/full_view.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/high_view.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/low_view.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/min_view.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/open_view.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/ranges_view.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/rates_view.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/vars_view.py +0 -0
- {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/volumes_view.py +0 -0
|
@@ -26,6 +26,11 @@ Cada migration deve implementar:
|
|
|
26
26
|
import importlib
|
|
27
27
|
from pathlib import Path
|
|
28
28
|
|
|
29
|
+
from ..logger import setup_logger
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
log = setup_logger(__name__)
|
|
33
|
+
|
|
29
34
|
|
|
30
35
|
MIGRATIONS_DIR = Path(__file__).parent
|
|
31
36
|
PACKAGE = "mtcli.migrations"
|
|
@@ -43,6 +48,8 @@ def ensure_migrations_table(conn):
|
|
|
43
48
|
aplicadas no banco.
|
|
44
49
|
"""
|
|
45
50
|
|
|
51
|
+
log.debug("Garantindo existência da tabela schema_migrations.")
|
|
52
|
+
|
|
46
53
|
conn.execute("""
|
|
47
54
|
CREATE TABLE IF NOT EXISTS schema_migrations(
|
|
48
55
|
version INTEGER PRIMARY KEY,
|
|
@@ -74,7 +81,11 @@ def get_current_version(conn):
|
|
|
74
81
|
|
|
75
82
|
row = cursor.fetchone()
|
|
76
83
|
|
|
77
|
-
|
|
84
|
+
version = row[0] if row and row[0] else 0
|
|
85
|
+
|
|
86
|
+
log.debug("Versão atual do schema: %s", version)
|
|
87
|
+
|
|
88
|
+
return version
|
|
78
89
|
|
|
79
90
|
|
|
80
91
|
def mark_version(conn, version):
|
|
@@ -82,6 +93,8 @@ def mark_version(conn, version):
|
|
|
82
93
|
Marca uma migration como aplicada.
|
|
83
94
|
"""
|
|
84
95
|
|
|
96
|
+
log.debug("Registrando migration aplicada: version=%s", version)
|
|
97
|
+
|
|
85
98
|
conn.execute(
|
|
86
99
|
"""
|
|
87
100
|
INSERT INTO schema_migrations(version, applied_at)
|
|
@@ -112,6 +125,8 @@ def discover_migrations():
|
|
|
112
125
|
list[(int,str)]
|
|
113
126
|
"""
|
|
114
127
|
|
|
128
|
+
log.debug("Descobrindo migrations em %s", MIGRATIONS_DIR)
|
|
129
|
+
|
|
115
130
|
migrations = []
|
|
116
131
|
|
|
117
132
|
for file in MIGRATIONS_DIR.glob("*.py"):
|
|
@@ -123,6 +138,7 @@ def discover_migrations():
|
|
|
123
138
|
|
|
124
139
|
# ignora arquivos inválidos
|
|
125
140
|
if not prefix.isdigit():
|
|
141
|
+
log.debug("Arquivo ignorado (prefixo inválido): %s", file.name)
|
|
126
142
|
continue
|
|
127
143
|
|
|
128
144
|
version = int(prefix)
|
|
@@ -133,6 +149,8 @@ def discover_migrations():
|
|
|
133
149
|
|
|
134
150
|
migrations.sort(key=lambda x: x[0])
|
|
135
151
|
|
|
152
|
+
log.debug("Migrations descobertas: %s", migrations)
|
|
153
|
+
|
|
136
154
|
validate_migrations(migrations)
|
|
137
155
|
|
|
138
156
|
return migrations
|
|
@@ -151,14 +169,21 @@ def validate_migrations(migrations):
|
|
|
151
169
|
versions = [v for v, _ in migrations]
|
|
152
170
|
|
|
153
171
|
if len(versions) != len(set(versions)):
|
|
172
|
+
|
|
173
|
+
log.error("Versões duplicadas detectadas nas migrations.")
|
|
174
|
+
|
|
154
175
|
raise RuntimeError("Duplicate migration versions detected.")
|
|
155
176
|
|
|
156
177
|
if not versions:
|
|
178
|
+
log.debug("Nenhuma migration encontrada.")
|
|
157
179
|
return
|
|
158
180
|
|
|
159
181
|
expected = list(range(min(versions), max(versions) + 1))
|
|
160
182
|
|
|
161
183
|
if versions != expected:
|
|
184
|
+
|
|
185
|
+
log.error("Gap detectado na sequência de migrations: %s", versions)
|
|
186
|
+
|
|
162
187
|
raise RuntimeError(
|
|
163
188
|
f"Migration sequence gap detected: {versions}"
|
|
164
189
|
)
|
|
@@ -173,6 +198,8 @@ def legacy_database_detected(conn):
|
|
|
173
198
|
Detecta bancos antigos sem controle de migrations.
|
|
174
199
|
"""
|
|
175
200
|
|
|
201
|
+
log.debug("Verificando se banco é legado.")
|
|
202
|
+
|
|
176
203
|
cursor = conn.execute("""
|
|
177
204
|
SELECT name
|
|
178
205
|
FROM sqlite_master
|
|
@@ -180,7 +207,12 @@ def legacy_database_detected(conn):
|
|
|
180
207
|
AND name='ticks'
|
|
181
208
|
""")
|
|
182
209
|
|
|
183
|
-
|
|
210
|
+
detected = cursor.fetchone() is not None
|
|
211
|
+
|
|
212
|
+
if detected:
|
|
213
|
+
log.info("Banco legado detectado (tabela ticks presente).")
|
|
214
|
+
|
|
215
|
+
return detected
|
|
184
216
|
|
|
185
217
|
|
|
186
218
|
def bootstrap_legacy(conn):
|
|
@@ -190,6 +222,8 @@ def bootstrap_legacy(conn):
|
|
|
190
222
|
|
|
191
223
|
if legacy_database_detected(conn):
|
|
192
224
|
|
|
225
|
+
log.info("Inicializando controle de migrations para banco legado.")
|
|
226
|
+
|
|
193
227
|
conn.execute("""
|
|
194
228
|
INSERT OR IGNORE INTO schema_migrations(version, applied_at)
|
|
195
229
|
VALUES (1, datetime('now'))
|
|
@@ -214,6 +248,8 @@ def run_migrations(conn):
|
|
|
214
248
|
4. Executa migrations pendentes
|
|
215
249
|
"""
|
|
216
250
|
|
|
251
|
+
log.debug("Iniciando verificação de migrations.")
|
|
252
|
+
|
|
217
253
|
ensure_migrations_table(conn)
|
|
218
254
|
|
|
219
255
|
bootstrap_legacy(conn)
|
|
@@ -222,24 +258,44 @@ def run_migrations(conn):
|
|
|
222
258
|
|
|
223
259
|
migrations = discover_migrations()
|
|
224
260
|
|
|
225
|
-
for
|
|
261
|
+
pending = [m for m in migrations if m[0] > current]
|
|
226
262
|
|
|
227
|
-
|
|
228
|
-
|
|
263
|
+
if not pending:
|
|
264
|
+
|
|
265
|
+
log.debug("Nenhuma migration pendente.")
|
|
266
|
+
|
|
267
|
+
return
|
|
268
|
+
|
|
269
|
+
log.info("Executando %s migration(s) pendente(s).", len(pending))
|
|
270
|
+
|
|
271
|
+
for version, module_name in pending:
|
|
229
272
|
|
|
230
273
|
module_path = f"{PACKAGE}.{module_name}"
|
|
231
274
|
|
|
275
|
+
log.info("Aplicando migration %s (%s)", version, module_name)
|
|
276
|
+
|
|
232
277
|
module = importlib.import_module(module_path)
|
|
233
278
|
|
|
234
279
|
if not hasattr(module, "upgrade"):
|
|
280
|
+
|
|
281
|
+
log.error("Migration %s não define upgrade()", module_name)
|
|
282
|
+
|
|
235
283
|
raise RuntimeError(
|
|
236
284
|
f"Migration {module_name} does not define upgrade()"
|
|
237
285
|
)
|
|
238
286
|
|
|
239
|
-
|
|
287
|
+
try:
|
|
288
|
+
|
|
289
|
+
module.upgrade(conn)
|
|
290
|
+
|
|
291
|
+
mark_version(conn, version)
|
|
292
|
+
|
|
293
|
+
log.info("Migration %s aplicada com sucesso.", version)
|
|
294
|
+
|
|
295
|
+
except Exception:
|
|
240
296
|
|
|
241
|
-
|
|
297
|
+
log.exception("Falha ao aplicar migration %s", version)
|
|
242
298
|
|
|
243
|
-
|
|
299
|
+
raise
|
|
244
300
|
|
|
245
|
-
|
|
301
|
+
log.info("Migrations concluídas com sucesso.")
|
|
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
|
|
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
|
{mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/003_optimize_ticks_without_rowid.py
RENAMED
|
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
|
|
File without changes
|
{mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/models/model_media_movel.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/tests/test_model_media_movel.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/models/average_range_model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/models/model_average_volume.py
RENAMED
|
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
|