slab-cli 0.1.0__tar.gz → 0.3.0__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 (28) hide show
  1. {slab_cli-0.1.0 → slab_cli-0.3.0}/PKG-INFO +1 -1
  2. {slab_cli-0.1.0 → slab_cli-0.3.0}/pyproject.toml +1 -1
  3. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/client.py +0 -5
  4. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/commands/catalog.py +8 -4
  5. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/commands/registry.py +0 -1
  6. slab_cli-0.3.0/src/slab_cli/commands/setup.py +23 -0
  7. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/context.py +11 -5
  8. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/help.py +16 -0
  9. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/main.py +3 -3
  10. slab_cli-0.1.0/src/slab_cli/commands/setup.py +0 -24
  11. {slab_cli-0.1.0 → slab_cli-0.3.0}/README.md +0 -0
  12. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/__init__.py +0 -0
  13. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/banner.py +0 -0
  14. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/commands/__init__.py +0 -0
  15. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/commands/breaks.py +0 -0
  16. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/commands/collection.py +0 -0
  17. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/commands/custom_sets.py +0 -0
  18. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/commands/export.py +0 -0
  19. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/commands/lots.py +0 -0
  20. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/commands/pricing.py +0 -0
  21. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/config.py +0 -0
  22. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/display.py +0 -0
  23. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/flags.py +0 -0
  24. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/paging.py +0 -0
  25. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/picker.py +0 -0
  26. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/prompts.py +0 -0
  27. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/sources.py +0 -0
  28. {slab_cli-0.1.0 → slab_cli-0.3.0}/src/slab_cli/theme.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: slab-cli
3
- Version: 0.1.0
3
+ Version: 0.3.0
4
4
  Summary: CLI for the slab trading-card API — catalog, collect, and track your cards from the terminal.
5
5
  Author: dev_jeb
6
6
  Requires-Dist: slab-schemas>=0.1.0
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "slab-cli"
3
- version = "0.1.0"
3
+ version = "0.3.0"
4
4
  description = "CLI for the slab trading-card API — catalog, collect, and track your cards from the terminal."
5
5
  readme = "README.md"
6
6
  authors = [{name = "dev_jeb"}]
@@ -36,7 +36,6 @@ from slab_schemas.collection import (
36
36
  CardCopyUpdate,
37
37
  CollectionResult,
38
38
  CollectionSearchQuery,
39
- CollectorCreate,
40
39
  CollectorOut,
41
40
  CollectorUpdate,
42
41
  )
@@ -207,10 +206,6 @@ class SlabClient:
207
206
 
208
207
  # --- collectors ---
209
208
 
210
- def create_collector(self, name: str) -> CollectorOut:
211
- resp = self._request("POST", "/collectors", json=CollectorCreate(name=name).model_dump(mode="json"))
212
- return CollectorOut.model_validate(resp.json())
213
-
214
209
  def rename_collector(self, collector_uuid: str, name: str) -> CollectorOut:
215
210
  resp = self._request(
216
211
  "PATCH", f"/collectors/{collector_uuid}", json=CollectorUpdate(name=name).model_dump(mode="json")
@@ -21,10 +21,14 @@ def cmd_search(args: list[str]) -> None:
21
21
  The same flags work on `slab collection search` — learn them once.
22
22
 
23
23
  Examples:
24
- slab card search McDavid --rookie
25
- slab card search Bedard --year 2025 --numbered
26
- slab card search --brand "Upper Deck" --base --limit 50
27
- slab card search --team "Minnesota Wild" --auto
24
+ slab card search McDavid --rookie # free text + one filter
25
+ slab card search Bedard --year 2025 --numbered # season + serial-numbered only
26
+ slab card search --team Bruins --team Leafs # any-of: either team
27
+ slab card search --brand "Upper Deck" --run-min 1 --run-max 99 # print-run range
28
+ slab card search McDavid --auto --parallel --sort -year # stack modifiers, newest first
29
+ slab card search --subset "Young Guns" --rookie --limit 50
30
+
31
+ Every flag combines with AND; repeat an any-of flag (--team, --brand, --finish…) to widen it.
28
32
 
29
33
  Sort keys: year, card_number, numbered, subject, brand, set (prefix - for descending).
30
34
  """
@@ -104,7 +104,6 @@ GROUPS: list[Group] = [
104
104
  Command("delete", "Delete a set you created", custom_sets.cmd_chase_delete),
105
105
  ]),
106
106
  Group("collector", "your identity", [
107
- Command("create", "Create a collector", setup.cmd_register, "<name>"),
108
107
  Command("current", "Show the active collector", setup.cmd_whoami),
109
108
  ]),
110
109
  ]
@@ -0,0 +1,23 @@
1
+ """Setup commands — check identity.
2
+
3
+ Collectors are NOT created here. Your account and its collector are provisioned when you sign up
4
+ in the portal; the CLI just consumes the API key and collector UUID you get there. When
5
+ SLAB_COLLECTOR is unset the CLI falls back to your account's default collector (see context.py),
6
+ so a solo user only needs their API key.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from ..config import get_collector_uuid
12
+ from ..display import console
13
+
14
+
15
+ def cmd_whoami(args: list[str]) -> None:
16
+ uuid = get_collector_uuid()
17
+ if uuid:
18
+ console.print(f"Active collector: [bold]{uuid}[/bold]")
19
+ else:
20
+ console.print(
21
+ "[dim]SLAB_COLLECTOR not set — the CLI will use your account's default collector.\n"
22
+ "Find your collector UUID and API key in the portal.[/dim]"
23
+ )
@@ -31,15 +31,21 @@ class CliContext:
31
31
 
32
32
  @property
33
33
  def collector(self) -> str:
34
- """The active collector UUID. Resolution order: SLAB_COLLECTOR env var, then the account's
35
- default collector (so a solo user only needs their API key). Raises MissingCollector if
36
- neither yields one. Cached per invocation."""
34
+ """The active collector UUID. Resolution order: SLAB_COLLECTOR env var, then for a
35
+ single-collector (`collector`) account only the account's default collector, so a solo
36
+ user needs just their API key. A `developer` account owns many collectors (one per
37
+ end-user), so there is NO safe default: it must set SLAB_COLLECTOR explicitly, or this
38
+ raises MissingCollector. Cached per invocation."""
37
39
  if self._collector:
38
40
  return self._collector
39
41
  uuid = get_collector_uuid()
40
42
  if not uuid:
41
- # Solo zero-config: fall back to the calling account's default collector.
42
- uuid = self.client.get_account_context().default_collector_uuid
43
+ # No explicit collector. Only a single-collector account may zero-config fall back to
44
+ # its default; a developer account has no unambiguous default and must set one.
45
+ me = self.client.get_account_context()
46
+ if me.account.account_type == "developer":
47
+ raise MissingCollector
48
+ uuid = me.default_collector_uuid
43
49
  if not uuid:
44
50
  raise MissingCollector
45
51
  self._collector = uuid
@@ -66,9 +66,25 @@ def render_command_help(group: Group, command: Command) -> None:
66
66
  for f in flags:
67
67
  grid.add_row(f" {f.usage()}", f.help)
68
68
  console.print(grid)
69
+ _render_query_grammar()
69
70
  console.print()
70
71
 
71
72
 
73
+ def _render_query_grammar() -> None:
74
+ """A generic primer on how the search grammar composes — printed under every command's flag
75
+ table. It describes the mechanics (free text, any-of, ranges, AND), never specific flags, so it
76
+ stays true no matter how the flag list evolves."""
77
+ console.print(Text.from_markup(
78
+ "\n [slab.label]Writing a query[/]"
79
+ "\n [slab.dim]Bare words are a free-text search (player, set…).[/]"
80
+ "\n [slab.dim]Flags narrow it, and every flag you add combines with AND.[/]"
81
+ "\n [slab.dim]Repeat an 'any-of' flag to match several values:[/] "
82
+ "[slab.value]--team Bruins --team Leafs[/]"
83
+ "\n [slab.dim]Pair a[/] [slab.value]--…-min[/] [slab.dim]with its[/] [slab.value]--…-max[/] "
84
+ "[slab.dim]for a range:[/] [slab.value]--run-min 1 --run-max 99[/]"
85
+ ))
86
+
87
+
72
88
  def render_root_help() -> None:
73
89
  """`slab` — the whole command surface, grouped by noun. The discovery home."""
74
90
  console.print(BANNER)
@@ -73,9 +73,9 @@ def main() -> None:
73
73
  console.print(f"[red]{e}[/red]")
74
74
  sys.exit(2)
75
75
  except MissingCollector:
76
- console.print("[red]No collector set.[/red]")
77
- console.print(" 1. Run: slab collector create <your name>")
78
- console.print(" 2. Run: export SLAB_COLLECTOR=<uuid from step 1>")
76
+ console.print("[red]No collector resolved for this API key.[/red]")
77
+ console.print(" Your collector is created when you sign up in the portal.")
78
+ console.print(" Grab its UUID there, then: export SLAB_COLLECTOR=<uuid>")
79
79
  sys.exit(1)
80
80
  except ApiConnectionError as e:
81
81
  console.print(f"\n[red]{e}[/red]")
@@ -1,24 +0,0 @@
1
- """Setup commands — register a collector, check identity."""
2
-
3
- from __future__ import annotations
4
-
5
- from ..config import get_collector_uuid
6
- from ..context import ctx
7
- from ..display import console
8
- from ..prompts import ask_text
9
-
10
-
11
- def cmd_register(args: list[str]) -> None:
12
- name = " ".join(args) if args else ask_text("Collector name:")
13
- collector = ctx.client.create_collector(name)
14
- console.print(f"\n[green]Collector created:[/green] {collector.name}")
15
- console.print(f" UUID: {collector.uuid}")
16
- console.print(f"\n Now run: [bold]export SLAB_COLLECTOR={collector.uuid}[/bold]")
17
-
18
-
19
- def cmd_whoami(args: list[str]) -> None:
20
- uuid = get_collector_uuid()
21
- if uuid:
22
- console.print(f"Active collector: [bold]{uuid}[/bold]")
23
- else:
24
- console.print("[dim]No collector set. Run: slab collector create <name>[/dim]")
File without changes
File without changes
File without changes