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.
Files changed (94) hide show
  1. {operx_cli-0.13.0 → operx_cli-0.13.1}/PKG-INFO +1 -1
  2. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/__init__.py +1 -1
  3. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/agent_guide.py +3 -1
  4. operx_cli-0.13.1/operx_cli/option_words.py +15 -0
  5. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/shell.py +5 -3
  6. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli.egg-info/PKG-INFO +1 -1
  7. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli.egg-info/SOURCES.txt +2 -0
  8. {operx_cli-0.13.0 → operx_cli-0.13.1}/pyproject.toml +1 -1
  9. operx_cli-0.13.1/tests/test_option_words.py +52 -0
  10. {operx_cli-0.13.0 → operx_cli-0.13.1}/README.md +0 -0
  11. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/AGENTES.md +0 -0
  12. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/api_fields.py +0 -0
  13. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/app.py +0 -0
  14. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/browser_login.py +0 -0
  15. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/client.py +0 -0
  16. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/__init__.py +0 -0
  17. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/account.py +0 -0
  18. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/ambiental.py +0 -0
  19. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/articulos.py +0 -0
  20. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/avisos.py +0 -0
  21. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/campos.py +0 -0
  22. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/chat.py +0 -0
  23. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/common.py +0 -0
  24. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/completar.py +0 -0
  25. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/connect.py +0 -0
  26. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/empresas.py +0 -0
  27. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/inventario.py +0 -0
  28. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/lecturas.py +0 -0
  29. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/muestreo.py +0 -0
  30. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/ordenes.py +0 -0
  31. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/personas.py +0 -0
  32. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/planta.py +0 -0
  33. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/preventivos.py +0 -0
  34. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/raw.py +0 -0
  35. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/registros.py +0 -0
  36. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/reportes.py +0 -0
  37. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/rutinas.py +0 -0
  38. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/search.py +0 -0
  39. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/sst.py +0 -0
  40. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/commands/update.py +0 -0
  41. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/forwarding/__init__.py +0 -0
  42. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/forwarding/buffer.py +0 -0
  43. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/forwarding/read.py +0 -0
  44. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/forwarding/run.py +0 -0
  45. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/forwarding/send.py +0 -0
  46. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/forwarding/sources.py +0 -0
  47. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/lookup.py +0 -0
  48. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/output.py +0 -0
  49. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/record_completion.py +0 -0
  50. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/self_update.py +0 -0
  51. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/settings.py +0 -0
  52. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/spreadsheet.py +0 -0
  53. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/updates.py +0 -0
  54. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/values.py +0 -0
  55. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli/welcome.py +0 -0
  56. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli.egg-info/dependency_links.txt +0 -0
  57. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli.egg-info/entry_points.txt +0 -0
  58. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli.egg-info/requires.txt +0 -0
  59. {operx_cli-0.13.0 → operx_cli-0.13.1}/operx_cli.egg-info/top_level.txt +0 -0
  60. {operx_cli-0.13.0 → operx_cli-0.13.1}/setup.cfg +0 -0
  61. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_agentes.py +0 -0
  62. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_api_campos.py +0 -0
  63. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_app.py +0 -0
  64. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_articulos.py +0 -0
  65. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_campos.py +0 -0
  66. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_cards.py +0 -0
  67. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_chat.py +0 -0
  68. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_client.py +0 -0
  69. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_completar.py +0 -0
  70. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_connect.py +0 -0
  71. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_daily_flows.py +0 -0
  72. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_forward.py +0 -0
  73. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_inventario_lecturas.py +0 -0
  74. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_json_writes.py +0 -0
  75. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_login.py +0 -0
  76. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_logout_and_routes.py +0 -0
  77. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_lookup.py +0 -0
  78. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_more_of_the_api.py +0 -0
  79. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_muestreo.py +0 -0
  80. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_ordenes.py +0 -0
  81. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_output.py +0 -0
  82. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_personas.py +0 -0
  83. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_preventivos.py +0 -0
  84. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_record_completion.py +0 -0
  85. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_registros.py +0 -0
  86. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_rutinas.py +0 -0
  87. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_self_update.py +0 -0
  88. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_settings.py +0 -0
  89. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_shell.py +0 -0
  90. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_spreadsheet.py +0 -0
  91. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_sst_ambiental.py +0 -0
  92. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_updates.py +0 -0
  93. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_values.py +0 -0
  94. {operx_cli-0.13.0 → operx_cli-0.13.1}/tests/test_welcome.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: operx-cli
3
- Version: 0.13.0
3
+ Version: 0.13.1
4
4
  Summary: La línea de comandos de OperX: tu empresa desde la terminal, con tu token de API.
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -2,4 +2,4 @@
2
2
  API (backend/users/api_allowlist.py) from a terminal, with a personal API
3
3
  token."""
4
4
 
5
- __version__ = "0.13.0"
5
+ __version__ = "0.13.1"
@@ -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 = getattr(param.type, "choices", None)
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 = getattr(option.type, "choices", None) or []
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 = getattr(getattr(param, "type", None), "choices", None)
160
+ choices = allowed_words(param) if param else []
160
161
  if choices:
161
- value = re.match(r"'(.*?)' is not", message)
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."
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: operx-cli
3
- Version: 0.13.0
3
+ Version: 0.13.1
4
4
  Summary: La línea de comandos de OperX: tu empresa desde la terminal, con tu token de API.
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -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.0"
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