operx-cli 0.13.0__tar.gz → 0.13.1__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.
- {operx_cli-0.13.0 → operx_cli-0.13.1}/PKG-INFO +1 -1
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/__init__.py +1 -1
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/agent_guide.py +3 -1
- operx_cli-0.13.1/operx_cli/option_words.py +15 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/shell.py +5 -3
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli.egg-info/PKG-INFO +1 -1
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli.egg-info/SOURCES.txt +2 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/pyproject.toml +1 -1
- operx_cli-0.13.1/tests/test_option_words.py +52 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/README.md +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/AGENTES.md +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/api_fields.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/app.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/browser_login.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/client.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/__init__.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/account.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/ambiental.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/articulos.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/avisos.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/campos.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/chat.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/common.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/completar.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/connect.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/empresas.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/inventario.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/lecturas.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/muestreo.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/ordenes.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/personas.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/planta.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/preventivos.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/raw.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/registros.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/reportes.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/rutinas.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/search.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/sst.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/update.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/forwarding/__init__.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/forwarding/buffer.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/forwarding/read.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/forwarding/run.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/forwarding/send.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/forwarding/sources.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/lookup.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/output.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/record_completion.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/self_update.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/settings.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/spreadsheet.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/updates.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/values.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/welcome.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli.egg-info/dependency_links.txt +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli.egg-info/entry_points.txt +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli.egg-info/requires.txt +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli.egg-info/top_level.txt +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/setup.cfg +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_agentes.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_api_campos.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_app.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_articulos.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_campos.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_cards.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_chat.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_client.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_completar.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_connect.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_daily_flows.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_forward.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_inventario_lecturas.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_json_writes.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_login.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_logout_and_routes.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_lookup.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_more_of_the_api.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_muestreo.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_ordenes.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_output.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_personas.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_preventivos.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_record_completion.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_registros.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_rutinas.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_self_update.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_settings.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_shell.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_spreadsheet.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_sst_ambiental.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_updates.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_values.py +0 -0
- {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_welcome.py +0 -0
|
@@ -4,6 +4,8 @@ installed version."""
|
|
|
4
4
|
|
|
5
5
|
from importlib.resources import files
|
|
6
6
|
|
|
7
|
+
from .option_words import allowed_words
|
|
8
|
+
|
|
7
9
|
ROOT_TITLE = "operx (opciones de cualquier comando)"
|
|
8
10
|
|
|
9
11
|
|
|
@@ -45,7 +47,7 @@ def _param_line(param):
|
|
|
45
47
|
line = f"`{param.name.upper()}`"
|
|
46
48
|
else:
|
|
47
49
|
line = ", ".join(f"`{opt}`" for opt in param.opts)
|
|
48
|
-
choices =
|
|
50
|
+
choices = allowed_words(param)
|
|
49
51
|
if choices:
|
|
50
52
|
line = f"`{' '.join(param.opts)} [{'|'.join(str(choice) for choice in choices)}]`"
|
|
51
53
|
elif not getattr(param, "is_flag", False):
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""The words a choice option allows, whichever version of Typer is installed.
|
|
2
|
+
|
|
3
|
+
Typer before 0.29 keeps an option's click type (`option.type.choices`, plain words). From 0.29 the option has no `type`:
|
|
4
|
+
its `type_descriptor` holds the `choices`, as the members of the enum the option was written with. The CLI asks for the
|
|
5
|
+
installed one by `typer>=0.27` only, so both shapes are read here."""
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def allowed_words(option):
|
|
9
|
+
"""The words a choice option allows, as text; empty for an option that is not a choice."""
|
|
10
|
+
descriptor = getattr(option, "type_descriptor", None)
|
|
11
|
+
if descriptor is not None:
|
|
12
|
+
choices = getattr(descriptor, "choices", None)
|
|
13
|
+
else:
|
|
14
|
+
choices = getattr(getattr(option, "type", None), "choices", None)
|
|
15
|
+
return [str(getattr(choice, "value", choice)) for choice in choices or []]
|
|
@@ -17,6 +17,7 @@ from rich.console import Console
|
|
|
17
17
|
from rich.text import Text
|
|
18
18
|
|
|
19
19
|
from . import __version__, settings
|
|
20
|
+
from .option_words import allowed_words
|
|
20
21
|
from .output import print_aligned
|
|
21
22
|
from .record_completion import RecordNames, completion_text
|
|
22
23
|
|
|
@@ -121,7 +122,7 @@ def suggestions(root, text, products=None):
|
|
|
121
122
|
|
|
122
123
|
option = _option_named(node, words[-1]) if words else None
|
|
123
124
|
if option is not None and not getattr(option, "is_flag", False):
|
|
124
|
-
choices =
|
|
125
|
+
choices = allowed_words(option)
|
|
125
126
|
return [(choice, "") for choice in choices if choice.startswith(current)]
|
|
126
127
|
|
|
127
128
|
if hasattr(node, "commands"):
|
|
@@ -156,9 +157,10 @@ def spanish_usage_error(error):
|
|
|
156
157
|
if suggested:
|
|
157
158
|
return f"No existe el comando «{typed}». ¿Quisiste decir {' o '.join(f'«{name}»' for name in suggested)}?"
|
|
158
159
|
return f"No existe el comando «{typed}». Escribe ayuda para ver los comandos."
|
|
159
|
-
choices =
|
|
160
|
+
choices = allowed_words(param) if param else []
|
|
160
161
|
if choices:
|
|
161
|
-
|
|
162
|
+
# Click says «'x' is not one of…»; Typer 0.29 puts «Value error, » before it.
|
|
163
|
+
value = re.search(r"'(.*?)' is not", message)
|
|
162
164
|
shown = f"«{value.group(1)}»" if value else "Ese valor"
|
|
163
165
|
return f"{shown} no sirve para {name}. Elige una de: {', '.join(choices)}."
|
|
164
166
|
return f"No entendí eso ({message}). Prueba con --help."
|
|
@@ -8,6 +8,7 @@ operx_cli/app.py
|
|
|
8
8
|
operx_cli/browser_login.py
|
|
9
9
|
operx_cli/client.py
|
|
10
10
|
operx_cli/lookup.py
|
|
11
|
+
operx_cli/option_words.py
|
|
11
12
|
operx_cli/output.py
|
|
12
13
|
operx_cli/record_completion.py
|
|
13
14
|
operx_cli/self_update.py
|
|
@@ -73,6 +74,7 @@ tests/test_logout_and_routes.py
|
|
|
73
74
|
tests/test_lookup.py
|
|
74
75
|
tests/test_more_of_the_api.py
|
|
75
76
|
tests/test_muestreo.py
|
|
77
|
+
tests/test_option_words.py
|
|
76
78
|
tests/test_ordenes.py
|
|
77
79
|
tests/test_output.py
|
|
78
80
|
tests/test_personas.py
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "operx-cli"
|
|
7
|
-
version = "0.13.
|
|
7
|
+
version = "0.13.1"
|
|
8
8
|
description = "La línea de comandos de OperX: tu empresa desde la terminal, con tu token de API."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""The words a choice option allows, read the same under every Typer the CLI accepts (typer>=0.27): the old click type's
|
|
2
|
+
plain words, and the enum members of the descriptor that Typer 0.29 keeps instead."""
|
|
3
|
+
|
|
4
|
+
import enum
|
|
5
|
+
from types import SimpleNamespace
|
|
6
|
+
|
|
7
|
+
import typer
|
|
8
|
+
from typer.main import get_command
|
|
9
|
+
|
|
10
|
+
from operx_cli.option_words import allowed_words
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Colour(str, enum.Enum):
|
|
14
|
+
rojo = "rojo"
|
|
15
|
+
azul = "azul"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _options_of_a_real_command():
|
|
19
|
+
app = typer.Typer()
|
|
20
|
+
|
|
21
|
+
@app.command()
|
|
22
|
+
def pinta(colour: Colour = Colour.rojo, copies: int = 1):
|
|
23
|
+
"""A command with a choice and a number."""
|
|
24
|
+
|
|
25
|
+
@app.command()
|
|
26
|
+
def otro():
|
|
27
|
+
"""A second command, so the app is a group."""
|
|
28
|
+
|
|
29
|
+
return {option.name: option for option in get_command(app).commands["pinta"].params}
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_a_real_choice_option_lists_its_words_and_a_number_lists_none():
|
|
33
|
+
options = _options_of_a_real_command()
|
|
34
|
+
|
|
35
|
+
assert allowed_words(options["colour"]) == ["rojo", "azul"]
|
|
36
|
+
assert allowed_words(options["copies"]) == []
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_the_old_shape_gives_plain_words():
|
|
40
|
+
old = SimpleNamespace(type=SimpleNamespace(choices=("uno", "dos")))
|
|
41
|
+
|
|
42
|
+
assert allowed_words(old) == ["uno", "dos"]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_the_new_shape_gives_the_enum_values_not_their_names():
|
|
46
|
+
new = SimpleNamespace(type_descriptor=SimpleNamespace(choices=(Colour.rojo, Colour.azul)))
|
|
47
|
+
|
|
48
|
+
assert allowed_words(new) == ["rojo", "azul"]
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_an_option_with_neither_shape_allows_nothing_in_particular():
|
|
52
|
+
assert allowed_words(SimpleNamespace()) == []
|
|
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
|
|
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
|
|
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
|