mtcli 3.7.0.dev2__py3-none-any.whl → 3.7.0.dev3__py3-none-any.whl
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/plugin_loader.py +134 -55
- {mtcli-3.7.0.dev2.dist-info → mtcli-3.7.0.dev3.dist-info}/METADATA +1 -1
- {mtcli-3.7.0.dev2.dist-info → mtcli-3.7.0.dev3.dist-info}/RECORD +6 -6
- {mtcli-3.7.0.dev2.dist-info → mtcli-3.7.0.dev3.dist-info}/WHEEL +0 -0
- {mtcli-3.7.0.dev2.dist-info → mtcli-3.7.0.dev3.dist-info}/entry_points.txt +0 -0
- {mtcli-3.7.0.dev2.dist-info → mtcli-3.7.0.dev3.dist-info}/licenses/LICENSE +0 -0
mtcli/plugin_loader.py
CHANGED
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Sistema de carregamento de plugins do mtcli.
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
instalados via entry points.
|
|
4
|
+
Este módulo descobre e registra plugins de duas fontes:
|
|
6
5
|
|
|
7
|
-
Plugins
|
|
6
|
+
1. Plugins internos localizados em ``mtcli.plugins``
|
|
7
|
+
2. Plugins externos registrados via entry points ``mtcli.plugins``
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Plugins podem expor:
|
|
10
|
+
|
|
11
|
+
• função ``register(cli)``
|
|
12
|
+
• objeto ``click.Command``
|
|
13
|
+
|
|
14
|
+
Entry point exemplo:
|
|
15
|
+
|
|
16
|
+
[project.entry-points."mtcli.plugins"]
|
|
17
|
+
renko = "mtcli_renko.plugin:register"
|
|
10
18
|
"""
|
|
11
19
|
|
|
12
20
|
from __future__ import annotations
|
|
13
21
|
|
|
22
|
+
import importlib
|
|
14
23
|
import logging
|
|
24
|
+
import pkgutil
|
|
15
25
|
from typing import Iterable, List
|
|
16
26
|
|
|
17
27
|
import click
|
|
@@ -21,15 +31,22 @@ try:
|
|
|
21
31
|
except ImportError: # pragma: no cover
|
|
22
32
|
from importlib_metadata import EntryPoint, entry_points
|
|
23
33
|
|
|
34
|
+
import mtcli.plugins
|
|
35
|
+
|
|
24
36
|
|
|
25
37
|
logger = logging.getLogger(__name__)
|
|
26
38
|
|
|
27
39
|
PLUGIN_GROUP = "mtcli.plugins"
|
|
28
40
|
|
|
29
41
|
|
|
30
|
-
|
|
42
|
+
# ---------------------------------------------------------
|
|
43
|
+
# Descoberta de plugins externos
|
|
44
|
+
# ---------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def discover_external_plugins() -> Iterable[EntryPoint]:
|
|
31
48
|
"""
|
|
32
|
-
Descobre plugins
|
|
49
|
+
Descobre plugins externos via entry points.
|
|
33
50
|
|
|
34
51
|
Returns
|
|
35
52
|
-------
|
|
@@ -38,110 +55,172 @@ def discover_plugins() -> Iterable[EntryPoint]:
|
|
|
38
55
|
"""
|
|
39
56
|
|
|
40
57
|
try:
|
|
58
|
+
eps = entry_points()
|
|
41
59
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
return entry_points(group=PLUGIN_GROUP)
|
|
45
|
-
except TypeError:
|
|
46
|
-
# Compatibilidade Python antigo
|
|
47
|
-
eps = entry_points()
|
|
48
|
-
|
|
49
|
-
if hasattr(eps, "select"):
|
|
50
|
-
return eps.select(group=PLUGIN_GROUP)
|
|
60
|
+
if hasattr(eps, "select"):
|
|
61
|
+
return eps.select(group=PLUGIN_GROUP)
|
|
51
62
|
|
|
52
|
-
|
|
63
|
+
return eps.get(PLUGIN_GROUP, [])
|
|
53
64
|
|
|
54
65
|
except Exception as exc: # pragma: no cover
|
|
55
|
-
logger.error("Erro ao descobrir plugins: %s", exc)
|
|
66
|
+
logger.error("Erro ao descobrir plugins externos: %s", exc)
|
|
56
67
|
return []
|
|
57
68
|
|
|
58
69
|
|
|
59
|
-
|
|
70
|
+
# ---------------------------------------------------------
|
|
71
|
+
# Registro de plugin
|
|
72
|
+
# ---------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def register_plugin(cli: click.Group, plugin, name: str) -> None:
|
|
60
76
|
"""
|
|
61
|
-
|
|
77
|
+
Registra um plugin no CLI.
|
|
62
78
|
|
|
63
|
-
O plugin pode
|
|
79
|
+
O plugin pode ser:
|
|
64
80
|
|
|
65
|
-
|
|
66
|
-
|
|
81
|
+
• função ``register(cli)``
|
|
82
|
+
• objeto ``click.Command``
|
|
67
83
|
|
|
68
84
|
Parameters
|
|
69
85
|
----------
|
|
70
86
|
cli : click.Group
|
|
71
87
|
CLI principal.
|
|
72
|
-
|
|
73
|
-
|
|
88
|
+
plugin : Any
|
|
89
|
+
Objeto do plugin carregado.
|
|
90
|
+
name : str
|
|
91
|
+
Nome do plugin.
|
|
74
92
|
"""
|
|
75
93
|
|
|
76
|
-
plugin = ep.load()
|
|
77
|
-
|
|
78
94
|
if callable(plugin) and not isinstance(plugin, click.Command):
|
|
79
|
-
|
|
80
95
|
plugin(cli)
|
|
81
|
-
|
|
82
|
-
logger.debug(
|
|
83
|
-
"Plugin '%s' registrado via função register() (%s)",
|
|
84
|
-
ep.name,
|
|
85
|
-
ep.value,
|
|
86
|
-
)
|
|
96
|
+
logger.debug("Plugin '%s' registrado via register()", name)
|
|
87
97
|
|
|
88
98
|
elif isinstance(plugin, click.Command):
|
|
89
|
-
|
|
90
99
|
cli.add_command(plugin)
|
|
91
|
-
|
|
92
|
-
logger.debug(
|
|
93
|
-
"Plugin '%s' registrado como comando Click (%s)",
|
|
94
|
-
ep.name,
|
|
95
|
-
ep.value,
|
|
96
|
-
)
|
|
100
|
+
logger.debug("Plugin '%s' registrado como comando", name)
|
|
97
101
|
|
|
98
102
|
else:
|
|
99
|
-
|
|
100
103
|
raise TypeError(
|
|
101
|
-
f"Plugin '{
|
|
102
|
-
"não é click.Command nem função register(cli)"
|
|
104
|
+
f"Plugin '{name}' inválido: não é click.Command nem register(cli)"
|
|
103
105
|
)
|
|
104
106
|
|
|
105
107
|
|
|
106
|
-
|
|
108
|
+
# ---------------------------------------------------------
|
|
109
|
+
# Plugins internos
|
|
110
|
+
# ---------------------------------------------------------
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def load_internal_plugins(cli: click.Group) -> List[str]:
|
|
107
114
|
"""
|
|
108
|
-
|
|
115
|
+
Carrega plugins internos do pacote ``mtcli.plugins``.
|
|
109
116
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
117
|
+
Cada módulo deve expor a função:
|
|
118
|
+
|
|
119
|
+
register(cli)
|
|
120
|
+
|
|
121
|
+
Returns
|
|
122
|
+
-------
|
|
123
|
+
list[str]
|
|
124
|
+
Lista de plugins carregados.
|
|
125
|
+
"""
|
|
126
|
+
|
|
127
|
+
loaded = []
|
|
128
|
+
|
|
129
|
+
for module_info in pkgutil.iter_modules(mtcli.plugins.__path__):
|
|
130
|
+
|
|
131
|
+
module_name = f"mtcli.plugins.{module_info.name}"
|
|
132
|
+
|
|
133
|
+
try:
|
|
134
|
+
module = importlib.import_module(module_name)
|
|
135
|
+
|
|
136
|
+
if hasattr(module, "register"):
|
|
137
|
+
module.register(cli)
|
|
138
|
+
loaded.append(module_info.name)
|
|
139
|
+
|
|
140
|
+
logger.debug("Plugin interno carregado: %s", module_info.name)
|
|
141
|
+
|
|
142
|
+
except Exception as exc:
|
|
143
|
+
logger.error(
|
|
144
|
+
"Falha ao carregar plugin interno '%s': %s",
|
|
145
|
+
module_info.name,
|
|
146
|
+
exc,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
return loaded
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
# ---------------------------------------------------------
|
|
153
|
+
# Plugins externos
|
|
154
|
+
# ---------------------------------------------------------
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def load_external_plugins(cli: click.Group) -> List[str]:
|
|
158
|
+
"""
|
|
159
|
+
Carrega plugins externos instalados via entry points.
|
|
114
160
|
|
|
115
161
|
Returns
|
|
116
162
|
-------
|
|
117
163
|
list[str]
|
|
118
|
-
Lista de plugins carregados
|
|
164
|
+
Lista de plugins carregados.
|
|
119
165
|
"""
|
|
120
166
|
|
|
121
|
-
loaded
|
|
167
|
+
loaded = []
|
|
122
168
|
seen = set()
|
|
123
169
|
|
|
124
|
-
for ep in
|
|
170
|
+
for ep in discover_external_plugins():
|
|
125
171
|
|
|
126
172
|
if ep.name in seen:
|
|
127
173
|
logger.warning("Plugin duplicado ignorado: %s", ep.name)
|
|
128
174
|
continue
|
|
129
175
|
|
|
130
176
|
try:
|
|
177
|
+
plugin = ep.load()
|
|
131
178
|
|
|
132
|
-
register_plugin(cli, ep)
|
|
179
|
+
register_plugin(cli, plugin, ep.name)
|
|
133
180
|
|
|
134
|
-
seen.add(ep.name)
|
|
135
181
|
loaded.append(ep.name)
|
|
182
|
+
seen.add(ep.name)
|
|
136
183
|
|
|
137
184
|
except Exception as exc:
|
|
138
|
-
|
|
139
185
|
logger.error(
|
|
140
186
|
"Falha ao carregar plugin '%s': %s",
|
|
141
187
|
ep.name,
|
|
142
188
|
exc,
|
|
143
189
|
)
|
|
144
190
|
|
|
191
|
+
return loaded
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
# ---------------------------------------------------------
|
|
195
|
+
# Loader principal
|
|
196
|
+
# ---------------------------------------------------------
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def load_plugins(cli: click.Group) -> List[str]:
|
|
200
|
+
"""
|
|
201
|
+
Carrega todos os plugins do mtcli.
|
|
202
|
+
|
|
203
|
+
Isso inclui:
|
|
204
|
+
|
|
205
|
+
• plugins internos
|
|
206
|
+
• plugins externos
|
|
207
|
+
|
|
208
|
+
Parameters
|
|
209
|
+
----------
|
|
210
|
+
cli : click.Group
|
|
211
|
+
CLI principal.
|
|
212
|
+
|
|
213
|
+
Returns
|
|
214
|
+
-------
|
|
215
|
+
list[str]
|
|
216
|
+
Lista com todos os plugins carregados.
|
|
217
|
+
"""
|
|
218
|
+
|
|
219
|
+
loaded = []
|
|
220
|
+
|
|
221
|
+
loaded.extend(load_internal_plugins(cli))
|
|
222
|
+
loaded.extend(load_external_plugins(cli))
|
|
223
|
+
|
|
145
224
|
logger.info("Plugins carregados: %d", len(loaded))
|
|
146
225
|
|
|
147
226
|
return loaded
|
|
@@ -28,7 +28,7 @@ mtcli/models/signals_model.py,sha256=XhyCErgyuHF0o85vnjIVJlgsCF7XFsWQltSbLZ3Aals
|
|
|
28
28
|
mtcli/models/unconsecutive_bar_model.py,sha256=AiClcoyYnk3K6D1YkC0E2PRUhbGwsjdSnh1vIHZsIe8,2079
|
|
29
29
|
mtcli/mt5_context.py,sha256=oLevCe4nYeZ6VtGoaO-j7U4xzACE09wGmX38P0oRg5A,2147
|
|
30
30
|
mtcli/plugin.py,sha256=Wabbr22BVi32D-XNM7XS45bRdgKob7EKO6TuWtq9_ZM,414
|
|
31
|
-
mtcli/plugin_loader.py,sha256=
|
|
31
|
+
mtcli/plugin_loader.py,sha256=tuL2dVYvyJpat5qagG1j3lJhEJRgAhKcn6lspNZr67w,5295
|
|
32
32
|
mtcli/plugin_manager.py,sha256=JTK6rmhjLa9MdyUiGgufAAnaaBhUI1Bm4g4t6p18WdU,555
|
|
33
33
|
mtcli/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
34
34
|
mtcli/plugins/exemplo.py-dist,sha256=q8H_sBpI-IZej9RvkCl2o_br9q2z_WXXn_qA1MRRbBo,538
|
|
@@ -65,8 +65,8 @@ mtcli/views/ranges_view.py,sha256=5gA2bAJuco-Xj964nsjs87tZ-079O7xKvaeif1UJ-PQ,12
|
|
|
65
65
|
mtcli/views/rates_view.py,sha256=Jkdbg-Q_OVJuID-Q9HFUVICCF1jE82d-qfZWNm1JJ_4,1214
|
|
66
66
|
mtcli/views/vars_view.py,sha256=Vpcej41qnZSvvSyvXYyW8W7CEFdqTxBd8NczV84XPJY,1635
|
|
67
67
|
mtcli/views/volumes_view.py,sha256=d_6YxM0vA1revwoPwnwUjV19KcqnddVgdpBHTt5Vqms,1575
|
|
68
|
-
mtcli-3.7.0.
|
|
69
|
-
mtcli-3.7.0.
|
|
70
|
-
mtcli-3.7.0.
|
|
71
|
-
mtcli-3.7.0.
|
|
72
|
-
mtcli-3.7.0.
|
|
68
|
+
mtcli-3.7.0.dev3.dist-info/entry_points.txt,sha256=sFL07BcOh-MKaij-M26bNlRbmlw9Xx0CTYTPtHegfI8,99
|
|
69
|
+
mtcli-3.7.0.dev3.dist-info/licenses/LICENSE,sha256=Z-2ANeRgM9IjXnHeg9mA2gillM6eTQj8sIExAGNe2-8,1092
|
|
70
|
+
mtcli-3.7.0.dev3.dist-info/METADATA,sha256=GFkl2N34O4Pj9I0P-ikGqTtkuDi48PW8L-K-jYQhG9M,3650
|
|
71
|
+
mtcli-3.7.0.dev3.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
72
|
+
mtcli-3.7.0.dev3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|