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.
Files changed (95) hide show
  1. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/PKG-INFO +1 -1
  2. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/runner.py +65 -9
  3. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/pyproject.toml +1 -1
  4. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/LICENSE +0 -0
  5. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/README.md +0 -0
  6. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/__init__.py +0 -0
  7. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/__main__.py +0 -0
  8. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/cli.py +0 -0
  9. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/cli_dev.py +0 -0
  10. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands/__init__.py +0 -0
  11. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands/backfill.py +0 -0
  12. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands/bars.py +0 -0
  13. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands/conf.py +0 -0
  14. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands/doctor.py +0 -0
  15. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands/ticks.py +0 -0
  16. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands_dev/__init__.py +0 -0
  17. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/commands_dev/migrate.py +0 -0
  18. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/conecta.py +0 -0
  19. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/conf.py +0 -0
  20. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/config_registre.py +0 -0
  21. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/data/__init__.py +0 -0
  22. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/data/base.py +0 -0
  23. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/data/csv.py +0 -0
  24. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/data/mt5.py +0 -0
  25. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/database.py +0 -0
  26. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/domain/__init__.py +0 -0
  27. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/domain/timeframe.py +0 -0
  28. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/logger.py +0 -0
  29. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/__init__.py +0 -0
  30. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/backfill_engine.py +0 -0
  31. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/tick_bus.py +0 -0
  32. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/tick_cache.py +0 -0
  33. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/tick_engine.py +0 -0
  34. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/tick_repository.py +0 -0
  35. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/marketdata/tick_writer.py +0 -0
  36. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/001_initial_schema.py +0 -0
  37. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/002_ticks_time_msc.py +0 -0
  38. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/003_optimize_ticks_without_rowid.py +0 -0
  39. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/004_ticks_pk_time_msc.py +0 -0
  40. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/005_tick_price_compression.py +0 -0
  41. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/006_add_index_ticks_symbol_time.py +0 -0
  42. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/007_deduplicate_ticks_and_add_unique_index.py +0 -0
  43. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/__init__.py +0 -0
  44. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/migrations/__main__.py +0 -0
  45. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/__init__.py +0 -0
  46. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/bar_model.py +0 -0
  47. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/bars_model.py +0 -0
  48. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/chart_model.py +0 -0
  49. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/conf_model.py +0 -0
  50. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/consecutive_bars_model.py +0 -0
  51. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/rates_model.py +0 -0
  52. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/signals_model.py +0 -0
  53. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/models/unconsecutive_bar_model.py +0 -0
  54. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/mt5_context.py +0 -0
  55. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugin.py +0 -0
  56. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugin_loader.py +0 -0
  57. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugin_manager.py +0 -0
  58. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/__init__.py +0 -0
  59. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/exemplo.py-dist +0 -0
  60. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/__init__.py +0 -0
  61. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/cli.py +0 -0
  62. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/conf.py +0 -0
  63. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/models/__init__.py +0 -0
  64. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/models/model_media_movel.py +0 -0
  65. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/tests/__init__.py +0 -0
  66. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/tests/test_mm.py +0 -0
  67. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/media_movel/tests/test_model_media_movel.py +0 -0
  68. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/__init__.py +0 -0
  69. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/cli.py +0 -0
  70. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/conf.py +0 -0
  71. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/models/__init__.py +0 -0
  72. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/models/average_range_model.py +0 -0
  73. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/tests/__init__.py +0 -0
  74. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/range_medio/tests/test_rm.py +0 -0
  75. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/__init__.py +0 -0
  76. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/cli.py +0 -0
  77. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/conf.py +0 -0
  78. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/models/__init__.py +0 -0
  79. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/models/model_average_volume.py +0 -0
  80. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/tests/__init__.py +0 -0
  81. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/plugins/volume_medio/tests/test_vm.py +0 -0
  82. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/services/__init__.py +0 -0
  83. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/services/maintenance_service.py +0 -0
  84. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/services/tick_service.py +0 -0
  85. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/__init__.py +0 -0
  86. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/close_view.py +0 -0
  87. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/full_view.py +0 -0
  88. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/high_view.py +0 -0
  89. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/low_view.py +0 -0
  90. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/min_view.py +0 -0
  91. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/open_view.py +0 -0
  92. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/ranges_view.py +0 -0
  93. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/rates_view.py +0 -0
  94. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/vars_view.py +0 -0
  95. {mtcli-3.8.0.dev13 → mtcli-3.8.0.dev14}/mtcli/views/volumes_view.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mtcli
3
- Version: 3.8.0.dev13
3
+ Version: 3.8.0.dev14
4
4
  Summary: Aplicativo CLI para exibir gráficos do MetaTrader 5 screen reader friendly
5
5
  License-Expression: MIT
6
6
  License-File: LICENSE
@@ -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
- return row[0] if row and row[0] else 0
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
- return cursor.fetchone() is not None
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 version, module_name in migrations:
261
+ pending = [m for m in migrations if m[0] > current]
226
262
 
227
- if version <= current:
228
- continue
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
- print(f"Applying migration {version}: {module_name}")
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
- module.upgrade(conn)
297
+ log.exception("Falha ao aplicar migration %s", version)
242
298
 
243
- mark_version(conn, version)
299
+ raise
244
300
 
245
- print("Migrations concluídas.")
301
+ log.info("Migrations concluídas com sucesso.")
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mtcli"
3
- version = "3.8.0.dev13"
3
+ version = "3.8.0.dev14"
4
4
  description = "Aplicativo CLI para exibir gráficos do MetaTrader 5 screen reader friendly"
5
5
  authors = [
6
6
  {name = "Valmir França",email = "vfranca3@gmail.com"}
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes