mtcli 3.7.0.dev0__tar.gz → 3.7.0.dev1__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 (72) hide show
  1. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/PKG-INFO +1 -1
  2. mtcli-3.7.0.dev1/mtcli/plugin_loader.py +147 -0
  3. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/pyproject.toml +1 -1
  4. mtcli-3.7.0.dev0/mtcli/plugin_loader.py +0 -81
  5. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/LICENSE +0 -0
  6. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/README.md +0 -0
  7. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/__init__.py +0 -0
  8. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/cli.py +0 -0
  9. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/commands/__init__.py +0 -0
  10. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/commands/bars.py +0 -0
  11. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/commands/conf.py +0 -0
  12. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/conecta.py +0 -0
  13. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/conf.py +0 -0
  14. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/config_registre.py +0 -0
  15. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/data/__init__.py +0 -0
  16. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/data/base.py +0 -0
  17. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/data/csv.py +0 -0
  18. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/data/mt5.py +0 -0
  19. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/database.py +0 -0
  20. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/domain/__init__.py +0 -0
  21. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/domain/timeframe.py +0 -0
  22. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/logger.py +0 -0
  23. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/marketdata/__init__.py +0 -0
  24. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/marketdata/tick_cache.py +0 -0
  25. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/marketdata/tick_repository.py +0 -0
  26. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/models/__init__.py +0 -0
  27. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/models/bar_model.py +0 -0
  28. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/models/bars_model.py +0 -0
  29. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/models/chart_model.py +0 -0
  30. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/models/conf_model.py +0 -0
  31. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/models/consecutive_bars_model.py +0 -0
  32. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/models/rates_model.py +0 -0
  33. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/models/signals_model.py +0 -0
  34. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/models/unconsecutive_bar_model.py +0 -0
  35. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/mt5_context.py +0 -0
  36. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugin.py +0 -0
  37. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugin_manager.py +0 -0
  38. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/__init__.py +0 -0
  39. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/exemplo.py-dist +0 -0
  40. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/media_movel/__init__.py +0 -0
  41. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/media_movel/cli.py +0 -0
  42. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/media_movel/conf.py +0 -0
  43. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/media_movel/models/__init__.py +0 -0
  44. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/media_movel/models/model_media_movel.py +0 -0
  45. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/media_movel/tests/__init__.py +0 -0
  46. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/media_movel/tests/test_mm.py +0 -0
  47. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/media_movel/tests/test_model_media_movel.py +0 -0
  48. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/range_medio/__init__.py +0 -0
  49. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/range_medio/cli.py +0 -0
  50. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/range_medio/conf.py +0 -0
  51. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/range_medio/models/__init__.py +0 -0
  52. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/range_medio/models/average_range_model.py +0 -0
  53. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/range_medio/tests/__init__.py +0 -0
  54. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/range_medio/tests/test_rm.py +0 -0
  55. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/volume_medio/__init__.py +0 -0
  56. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/volume_medio/cli.py +0 -0
  57. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/volume_medio/conf.py +0 -0
  58. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/volume_medio/models/__init__.py +0 -0
  59. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/volume_medio/models/model_average_volume.py +0 -0
  60. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/volume_medio/tests/__init__.py +0 -0
  61. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/plugins/volume_medio/tests/test_vm.py +0 -0
  62. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/views/__init__.py +0 -0
  63. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/views/close_view.py +0 -0
  64. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/views/full_view.py +0 -0
  65. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/views/high_view.py +0 -0
  66. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/views/low_view.py +0 -0
  67. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/views/min_view.py +0 -0
  68. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/views/open_view.py +0 -0
  69. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/views/ranges_view.py +0 -0
  70. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/views/rates_view.py +0 -0
  71. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/views/vars_view.py +0 -0
  72. {mtcli-3.7.0.dev0 → mtcli-3.7.0.dev1}/mtcli/views/volumes_view.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mtcli
3
- Version: 3.7.0.dev0
3
+ Version: 3.7.0.dev1
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
@@ -0,0 +1,147 @@
1
+ """
2
+ Sistema de carregamento de plugins do mtcli.
3
+
4
+ Este módulo é responsável por descobrir e registrar plugins externos
5
+ instalados via entry points do Python.
6
+
7
+ Plugins devem declarar entry points no grupo:
8
+
9
+ mtcli.plugins
10
+
11
+ Um plugin pode expor:
12
+
13
+ 1. Uma função ``register(cli)``
14
+ 2. Um objeto ``click.Command``
15
+
16
+ Exemplo de entry point no pyproject.toml:
17
+
18
+ [project.entry-points."mtcli.plugins"]
19
+ renko = "mtcli_renko.plugin:register"
20
+
21
+ Ou diretamente um comando:
22
+
23
+ renko = "mtcli_renko.cli:renko"
24
+
25
+ Este loader garante:
26
+
27
+ - compatibilidade com Python 3.8+
28
+ - proteção contra plugins duplicados
29
+ - logging estruturado
30
+ - isolamento de falhas de plugins
31
+ """
32
+
33
+ from __future__ import annotations
34
+
35
+ import logging
36
+ from typing import Iterable, List
37
+
38
+ import click
39
+
40
+ try:
41
+ from importlib.metadata import EntryPoint, entry_points
42
+ except ImportError: # pragma: no cover
43
+ from importlib_metadata import EntryPoint, entry_points
44
+
45
+
46
+ logger = logging.getLogger(__name__)
47
+
48
+ PLUGIN_GROUP = "mtcli.plugins"
49
+
50
+
51
+ def discover_plugins() -> Iterable[EntryPoint]:
52
+ """
53
+ Descobre plugins registrados via entry points.
54
+
55
+ Returns
56
+ -------
57
+ Iterable[EntryPoint]
58
+ Lista de entry points encontrados no grupo ``mtcli.plugins``.
59
+ """
60
+
61
+ try:
62
+ eps = entry_points()
63
+
64
+ if hasattr(eps, "select"):
65
+ return eps.select(group=PLUGIN_GROUP)
66
+
67
+ return eps.get(PLUGIN_GROUP, [])
68
+
69
+ except Exception as exc: # pragma: no cover
70
+ logger.error("Erro ao descobrir plugins: %s", exc)
71
+ return []
72
+
73
+
74
+ def register_plugin(cli: click.Group, ep: EntryPoint) -> None:
75
+ """
76
+ Carrega e registra um plugin individual.
77
+
78
+ O plugin pode ser:
79
+
80
+ - função register(cli)
81
+ - objeto click.Command
82
+
83
+ Parameters
84
+ ----------
85
+ cli : click.Group
86
+ CLI principal do mtcli.
87
+ ep : EntryPoint
88
+ Entry point do plugin.
89
+ """
90
+
91
+ plugin = ep.load()
92
+
93
+ if callable(plugin) and not isinstance(plugin, click.Command):
94
+ plugin(cli)
95
+ logger.debug("Plugin '%s' registrado via register()", ep.name)
96
+
97
+ elif isinstance(plugin, click.Command):
98
+ cli.add_command(plugin)
99
+ logger.debug("Plugin '%s' registrado como comando", ep.name)
100
+
101
+ else:
102
+ raise TypeError(
103
+ f"Plugin '{ep.name}' inválido: "
104
+ "não é click.Command nem função register(cli)"
105
+ )
106
+
107
+
108
+ def load_plugins(cli: click.Group) -> List[str]:
109
+ """
110
+ Descobre e carrega todos os plugins instalados.
111
+
112
+ Parameters
113
+ ----------
114
+ cli : click.Group
115
+ CLI principal do mtcli.
116
+
117
+ Returns
118
+ -------
119
+ list[str]
120
+ Lista com os nomes dos plugins carregados com sucesso.
121
+ """
122
+
123
+ loaded: List[str] = []
124
+ seen = set()
125
+
126
+ for ep in discover_plugins():
127
+
128
+ if ep.name in seen:
129
+ logger.warning("Plugin duplicado ignorado: %s", ep.name)
130
+ continue
131
+
132
+ try:
133
+ register_plugin(cli, ep)
134
+
135
+ seen.add(ep.name)
136
+ loaded.append(ep.name)
137
+
138
+ except Exception as exc:
139
+ logger.error(
140
+ "Falha ao carregar plugin '%s': %s",
141
+ ep.name,
142
+ exc,
143
+ )
144
+
145
+ logger.info("Plugins carregados: %d", len(loaded))
146
+
147
+ return loaded
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mtcli"
3
- version = "3.7.0.dev0"
3
+ version = "3.7.0.dev1"
4
4
  description = "Aplicativo CLI para exibir gráficos do MetaTrader 5 screen reader friendly"
5
5
  authors = [
6
6
  {name = "Valmir França da Silva",email = "vfranca3@gmail.com"}
@@ -1,81 +0,0 @@
1
- """
2
- Carregador de plugins do mtcli.
3
-
4
- Responsável por descobrir e registrar plugins internos e externos
5
- utilizando entry points.
6
-
7
- Plugins podem expor:
8
-
9
- 1. função register(cli)
10
- 2. objeto click.Command
11
- """
12
-
13
- import logging
14
- import click
15
-
16
- try:
17
- from importlib.metadata import entry_points
18
- except ImportError: # pragma: no cover
19
- from importlib_metadata import entry_points
20
-
21
-
22
- logger = logging.getLogger(__name__)
23
-
24
-
25
- def load_plugins(cli):
26
- """
27
- Descobre e carrega plugins registrados via entry points.
28
-
29
- Args:
30
- cli (click.Group): CLI principal.
31
- """
32
-
33
- try:
34
- eps = entry_points()
35
-
36
- plugins = (
37
- eps.select(group="mtcli.plugins")
38
- if hasattr(eps, "select")
39
- else eps.get("mtcli.plugins", [])
40
- )
41
-
42
- except Exception as exc:
43
- logger.error("Erro ao descobrir plugins: %s", exc)
44
- return
45
-
46
- loaded = set()
47
-
48
- for ep in plugins:
49
-
50
- if ep.name in loaded:
51
- logger.warning("Plugin duplicado ignorado: %s", ep.name)
52
- continue
53
-
54
- try:
55
-
56
- plugin = ep.load()
57
-
58
- # função register(cli)
59
- if callable(plugin) and not isinstance(plugin, click.Command):
60
- plugin(cli)
61
-
62
- # comando click direto
63
- elif isinstance(plugin, click.Command):
64
- cli.add_command(plugin)
65
-
66
- else:
67
- raise TypeError(
68
- "Plugin não é comando Click nem função register(cli)"
69
- )
70
-
71
- loaded.add(ep.name)
72
-
73
- logger.debug("Plugin carregado: %s", ep.name)
74
-
75
- except Exception as exc:
76
-
77
- logger.error(
78
- "Falha ao carregar plugin '%s': %s",
79
- ep.name,
80
- exc,
81
- )
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