operx-cli 0.2.1__tar.gz → 0.2.2__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.2.1 → operx_cli-0.2.2}/PKG-INFO +1 -1
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/__init__.py +1 -1
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/app.py +1 -1
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/commands/account.py +2 -1
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/shell.py +14 -3
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli.egg-info/PKG-INFO +1 -1
- {operx_cli-0.2.1 → operx_cli-0.2.2}/pyproject.toml +1 -1
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_app.py +3 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_shell.py +43 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/README.md +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/AGENTES.md +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/agent_guide.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/browser_login.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/client.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/commands/__init__.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/commands/common.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/commands/inventario.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/commands/lecturas.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/commands/ordenes.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/commands/personas.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/commands/raw.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/commands/registros.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/commands/search.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/lookup.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/output.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/settings.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/spreadsheet.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/values.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli/welcome.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli.egg-info/SOURCES.txt +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli.egg-info/dependency_links.txt +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli.egg-info/entry_points.txt +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli.egg-info/requires.txt +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/operx_cli.egg-info/top_level.txt +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/setup.cfg +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_agentes.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_client.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_inventario_lecturas.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_login.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_lookup.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_ordenes.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_output.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_personas.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_registros.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_settings.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_spreadsheet.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_values.py +0 -0
- {operx_cli-0.2.1 → operx_cli-0.2.2}/tests/test_welcome.py +0 -0
|
@@ -136,7 +136,7 @@ app.add_typer(personas.app, name="personas")
|
|
|
136
136
|
|
|
137
137
|
@app.command()
|
|
138
138
|
def agentes(ctx: typer.Context):
|
|
139
|
-
"""La guía para
|
|
139
|
+
"""La guía para que un agente de IA (Claude, ChatGPT…) use operx bien."""
|
|
140
140
|
typer.echo(guide_text(ctx.find_root().command))
|
|
141
141
|
|
|
142
142
|
|
|
@@ -100,5 +100,6 @@ def cuenta(ctx: typer.Context, as_json: JsonOption = False):
|
|
|
100
100
|
"Rol": [role for role in roles if role],
|
|
101
101
|
"Productos": [PRODUCT_LABELS.get(product, product) for product in me.get("products") or []],
|
|
102
102
|
"Perfil": session.profile,
|
|
103
|
-
|
|
103
|
+
# The API's address, the same for every company (not acme.operx.pro, the app's).
|
|
104
|
+
"API": session.address(),
|
|
104
105
|
}, "tabla")
|
|
@@ -13,6 +13,8 @@ import shlex
|
|
|
13
13
|
|
|
14
14
|
import typer
|
|
15
15
|
from rich.console import Console
|
|
16
|
+
from rich.padding import Padding
|
|
17
|
+
from rich.table import Table
|
|
16
18
|
from rich.text import Text
|
|
17
19
|
|
|
18
20
|
from . import settings
|
|
@@ -21,8 +23,12 @@ PROMPT = "operx › "
|
|
|
21
23
|
STOP_WORDS = ("salir", "exit", "quit")
|
|
22
24
|
HELP_WORDS = ("/ayuda", "ayuda", "/help", "help", "?")
|
|
23
25
|
CLEAR_WORDS = ("limpiar", "/limpiar", "clear", "cls")
|
|
24
|
-
# What the prompt offers besides the commands
|
|
25
|
-
SHELL_WORDS = [
|
|
26
|
+
# What the prompt offers besides the commands, with the other words that do the same.
|
|
27
|
+
SHELL_WORDS = [
|
|
28
|
+
("limpiar", "Limpia la pantalla. También: clear, cls."),
|
|
29
|
+
("salir", "Termina esta sesión. No borra tu token. También: exit, quit, Ctrl+D."),
|
|
30
|
+
("ayuda", "Muestra los comandos. También: help, ?."),
|
|
31
|
+
]
|
|
26
32
|
AMBER = "#fbbf24"
|
|
27
33
|
|
|
28
34
|
|
|
@@ -111,8 +117,13 @@ def spanish_usage_error(error):
|
|
|
111
117
|
def print_help(root, console):
|
|
112
118
|
console.print(Text("Comandos", style=f"bold {AMBER}"))
|
|
113
119
|
commands = [(name, _first_line(command.help)) for name, command in root.commands.items() if _visible(command)]
|
|
120
|
+
# Two columns: on a narrow screen a long description wraps inside its own.
|
|
121
|
+
table = Table.grid(padding=(0, 2))
|
|
122
|
+
table.add_column(style="bold", no_wrap=True)
|
|
123
|
+
table.add_column()
|
|
114
124
|
for name, help_text in commands + SHELL_WORDS:
|
|
115
|
-
|
|
125
|
+
table.add_row(name, help_text)
|
|
126
|
+
console.print(Padding(table, (0, 0, 0, 2)))
|
|
116
127
|
console.print(Text("Escribe un comando con --help para ver sus opciones.", style="dim"))
|
|
117
128
|
|
|
118
129
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "operx-cli"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
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"
|
|
@@ -70,6 +70,9 @@ def test_cuenta_shows_who_and_where(signed_in):
|
|
|
70
70
|
assert result.exit_code == 0, result.output
|
|
71
71
|
for text in ("Ana Ruiz", "ana@acme.co", "Acme S.A.S.", "Administrador", "Trabajos, Personas", "https://api.operx.pro"):
|
|
72
72
|
assert text in result.output
|
|
73
|
+
# The API's address, the same for every company: not the company's web address.
|
|
74
|
+
api_line = next(line for line in result.output.splitlines() if "https://api.operx.pro" in line)
|
|
75
|
+
assert api_line.startswith("API ")
|
|
73
76
|
|
|
74
77
|
|
|
75
78
|
def test_buscar_lists_what_the_top_bar_finds(signed_in):
|
|
@@ -206,6 +206,49 @@ def test_ayuda_lists_the_commands(capsys):
|
|
|
206
206
|
assert "entrar" not in out
|
|
207
207
|
|
|
208
208
|
|
|
209
|
+
def test_ayuda_lists_every_word_the_prompt_understands(capsys):
|
|
210
|
+
shell(FakeApi({}), "ayuda")
|
|
211
|
+
out = capsys.readouterr().out
|
|
212
|
+
for word in ("salir", "exit", "quit", "Ctrl+D", "limpiar", "clear", "cls", "ayuda", "help", "?"):
|
|
213
|
+
assert word in out
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def test_limpiar_is_offered_while_typing():
|
|
217
|
+
assert "limpiar" in names(suggestions(ROOT, "lim"))
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def test_ayuda_keeps_a_long_description_in_its_own_column_on_a_narrow_screen():
|
|
221
|
+
import io
|
|
222
|
+
|
|
223
|
+
from rich.console import Console
|
|
224
|
+
|
|
225
|
+
from operx_cli.shell import print_help
|
|
226
|
+
|
|
227
|
+
out = io.StringIO()
|
|
228
|
+
print_help(ROOT, Console(file=out, width=60, force_terminal=False, color_system=None))
|
|
229
|
+
lines = out.getvalue().splitlines()
|
|
230
|
+
column = lines[1].index("Entra con tu cuenta")
|
|
231
|
+
wrapped = [line for line in lines[1:-1] if line[:column].strip() == ""]
|
|
232
|
+
|
|
233
|
+
assert wrapped # at 60 columns some descriptions take two lines
|
|
234
|
+
for line in wrapped:
|
|
235
|
+
assert line[column - 1] == " " and line[column] != " "
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def test_every_description_fits_one_line_on_a_common_screen():
|
|
239
|
+
import io
|
|
240
|
+
|
|
241
|
+
from rich.console import Console
|
|
242
|
+
|
|
243
|
+
from operx_cli.shell import print_help
|
|
244
|
+
|
|
245
|
+
out = io.StringIO()
|
|
246
|
+
print_help(ROOT, Console(file=out, width=120, force_terminal=False, color_system=None))
|
|
247
|
+
lines = out.getvalue().splitlines()[1:-1]
|
|
248
|
+
|
|
249
|
+
assert all(line[:2] == " " and line[2] != " " for line in lines)
|
|
250
|
+
|
|
251
|
+
|
|
209
252
|
def test_the_old_names_stay_out_of_what_is_offered(capsys):
|
|
210
253
|
shell(FakeApi({}), "ayuda")
|
|
211
254
|
assert "entrar" not in capsys.readouterr().out
|
|
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
|