cli-web-amazon 0.1.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.
- cli_web_amazon-0.1.1/PKG-INFO +14 -0
- cli_web_amazon-0.1.1/cli_web/amazon/README.md +83 -0
- cli_web_amazon-0.1.1/cli_web/amazon/__init__.py +3 -0
- cli_web_amazon-0.1.1/cli_web/amazon/__main__.py +6 -0
- cli_web_amazon-0.1.1/cli_web/amazon/amazon_cli.py +155 -0
- cli_web_amazon-0.1.1/cli_web/amazon/commands/__init__.py +1 -0
- cli_web_amazon-0.1.1/cli_web/amazon/commands/bestsellers.py +61 -0
- cli_web_amazon-0.1.1/cli_web/amazon/commands/product.py +36 -0
- cli_web_amazon-0.1.1/cli_web/amazon/commands/search.py +45 -0
- cli_web_amazon-0.1.1/cli_web/amazon/commands/suggest.py +36 -0
- cli_web_amazon-0.1.1/cli_web/amazon/core/__init__.py +1 -0
- cli_web_amazon-0.1.1/cli_web/amazon/core/client.py +416 -0
- cli_web_amazon-0.1.1/cli_web/amazon/core/exceptions.py +76 -0
- cli_web_amazon-0.1.1/cli_web/amazon/core/models.py +63 -0
- cli_web_amazon-0.1.1/cli_web/amazon/skills/SKILL.md +105 -0
- cli_web_amazon-0.1.1/cli_web/amazon/tests/TEST.md +173 -0
- cli_web_amazon-0.1.1/cli_web/amazon/tests/__init__.py +1 -0
- cli_web_amazon-0.1.1/cli_web/amazon/tests/test_core.py +369 -0
- cli_web_amazon-0.1.1/cli_web/amazon/tests/test_e2e.py +355 -0
- cli_web_amazon-0.1.1/cli_web/amazon/utils/__init__.py +1 -0
- cli_web_amazon-0.1.1/cli_web/amazon/utils/config.py +5 -0
- cli_web_amazon-0.1.1/cli_web/amazon/utils/doctor.py +188 -0
- cli_web_amazon-0.1.1/cli_web/amazon/utils/helpers.py +127 -0
- cli_web_amazon-0.1.1/cli_web/amazon/utils/mcp_server.py +290 -0
- cli_web_amazon-0.1.1/cli_web/amazon/utils/output.py +130 -0
- cli_web_amazon-0.1.1/cli_web/amazon/utils/repl_skin.py +486 -0
- cli_web_amazon-0.1.1/cli_web_amazon.egg-info/PKG-INFO +14 -0
- cli_web_amazon-0.1.1/cli_web_amazon.egg-info/SOURCES.txt +32 -0
- cli_web_amazon-0.1.1/cli_web_amazon.egg-info/dependency_links.txt +1 -0
- cli_web_amazon-0.1.1/cli_web_amazon.egg-info/entry_points.txt +2 -0
- cli_web_amazon-0.1.1/cli_web_amazon.egg-info/requires.txt +6 -0
- cli_web_amazon-0.1.1/cli_web_amazon.egg-info/top_level.txt +1 -0
- cli_web_amazon-0.1.1/setup.cfg +4 -0
- cli_web_amazon-0.1.1/setup.py +25 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: cli-web-amazon
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Amazon CLI — Search, browse, and shop Amazon from your terminal
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Requires-Dist: click>=8.0
|
|
7
|
+
Requires-Dist: httpx>=0.25
|
|
8
|
+
Requires-Dist: curl_cffi>=0.7
|
|
9
|
+
Requires-Dist: beautifulsoup4>=4.12
|
|
10
|
+
Requires-Dist: rich>=13.0
|
|
11
|
+
Requires-Dist: prompt_toolkit>=3.0
|
|
12
|
+
Dynamic: requires-dist
|
|
13
|
+
Dynamic: requires-python
|
|
14
|
+
Dynamic: summary
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# cli-web-amazon
|
|
2
|
+
|
|
3
|
+
> Generated by [CLI-Anything-Web](../../../../cli-anything-web-plugin/) from [amazon.com](https://www.amazon.com)
|
|
4
|
+
|
|
5
|
+
Search Amazon products, view details, browse Best Sellers, and get autocomplete suggestions. No authentication required — all commands use public Amazon endpoints.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install cli-web-amazon
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Search
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
cli-web-amazon search "laptop"
|
|
19
|
+
cli-web-amazon search "headphones" --dept electronics --page 2
|
|
20
|
+
cli-web-amazon search "coffee maker" --json
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Autocomplete Suggestions
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
cli-web-amazon suggest "headp"
|
|
27
|
+
cli-web-amazon suggest "lapt" --json
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Product Details
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
cli-web-amazon product get B0GRZ78683
|
|
34
|
+
cli-web-amazon product get B0GRZ78683 --json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Best Sellers
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
cli-web-amazon bestsellers electronics
|
|
41
|
+
cli-web-amazon bestsellers books --page 2
|
|
42
|
+
cli-web-amazon bestsellers --json
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## JSON Output
|
|
46
|
+
|
|
47
|
+
Every command supports `--json` for structured output suitable for piping and scripting:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
cli-web-amazon search "laptop" --json | jq '.[0]'
|
|
51
|
+
cli-web-amazon product get B0GRZ78683 --json | jq '.price'
|
|
52
|
+
cli-web-amazon bestsellers electronics --json | jq '.[].title'
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## REPL Mode
|
|
56
|
+
|
|
57
|
+
Run without arguments to enter interactive REPL mode:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cli-web-amazon
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Type `help` inside the REPL to see all available commands.
|
|
64
|
+
|
|
65
|
+
## Testing
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
cd amazon/agent-harness
|
|
69
|
+
pip install -e .
|
|
70
|
+
|
|
71
|
+
# Unit tests (no network)
|
|
72
|
+
python -m pytest cli_web/amazon/tests/test_core.py -v
|
|
73
|
+
|
|
74
|
+
# All tests including E2E
|
|
75
|
+
python -m pytest cli_web/amazon/tests/ -v -s
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Protocol
|
|
79
|
+
|
|
80
|
+
- **Website:** https://www.amazon.com
|
|
81
|
+
- **Protocol:** SSR HTML + REST JSON hybrid
|
|
82
|
+
- **Auth:** None — all commands use public Amazon endpoints
|
|
83
|
+
- **HTTP library:** curl_cffi (Chrome impersonation — bypasses Amazon's 503 bot block)
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"""cli-web-amazon entry point — Amazon CLI."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
# Windows UTF-8 fix — must be before any imports that print
|
|
6
|
+
if sys.stdout.encoding and sys.stdout.encoding.lower() not in ("utf-8", "utf8"):
|
|
7
|
+
try:
|
|
8
|
+
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
|
9
|
+
except AttributeError:
|
|
10
|
+
pass
|
|
11
|
+
if sys.stderr.encoding and sys.stderr.encoding.lower() not in ("utf-8", "utf8"):
|
|
12
|
+
try:
|
|
13
|
+
sys.stderr.reconfigure(encoding="utf-8", errors="replace")
|
|
14
|
+
except AttributeError:
|
|
15
|
+
pass
|
|
16
|
+
|
|
17
|
+
import shlex
|
|
18
|
+
|
|
19
|
+
import click
|
|
20
|
+
|
|
21
|
+
from .commands.bestsellers import bestsellers
|
|
22
|
+
from .commands.product import product
|
|
23
|
+
from .commands.search import search
|
|
24
|
+
from .commands.suggest import suggest
|
|
25
|
+
from .core.exceptions import AmazonError
|
|
26
|
+
from .utils.repl_skin import ReplSkin
|
|
27
|
+
|
|
28
|
+
__version__ = "1.0.0"
|
|
29
|
+
|
|
30
|
+
_skin = ReplSkin("amazon", version=__version__)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def _print_repl_help():
|
|
34
|
+
"""Print REPL command reference."""
|
|
35
|
+
_skin.info("Available commands:")
|
|
36
|
+
print()
|
|
37
|
+
print(" suggest <query> Autocomplete suggestions")
|
|
38
|
+
print(" search <query> [OPTIONS] Search Amazon products")
|
|
39
|
+
print(" --page N Page number (default: 1)")
|
|
40
|
+
print(" --dept <department> Department filter")
|
|
41
|
+
print()
|
|
42
|
+
print(" product get <ASIN> Product detail by ASIN")
|
|
43
|
+
print()
|
|
44
|
+
print(" bestsellers [<category>] Best Sellers list")
|
|
45
|
+
print(" category: electronics, books, toys-and-games, music, ...")
|
|
46
|
+
print(" --page N Page number")
|
|
47
|
+
print()
|
|
48
|
+
print(" Global options: --json Output as JSON")
|
|
49
|
+
print()
|
|
50
|
+
print(" help Show this help")
|
|
51
|
+
print(" quit Exit REPL")
|
|
52
|
+
print()
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@click.group(invoke_without_command=True)
|
|
56
|
+
@click.option(
|
|
57
|
+
"--json", "json_mode", is_flag=True, default=False, help="Output all results as JSON."
|
|
58
|
+
)
|
|
59
|
+
@click.version_option(__version__, "--version", "-V")
|
|
60
|
+
@click.pass_context
|
|
61
|
+
def cli(ctx, json_mode):
|
|
62
|
+
"""cli-web-amazon — Browse and search Amazon from your terminal.
|
|
63
|
+
|
|
64
|
+
Run without a subcommand to enter interactive REPL mode.
|
|
65
|
+
|
|
66
|
+
Examples:
|
|
67
|
+
cli-web-amazon search laptop
|
|
68
|
+
cli-web-amazon product get B0GRZ78683
|
|
69
|
+
cli-web-amazon bestsellers electronics
|
|
70
|
+
cli-web-amazon suggest headphones
|
|
71
|
+
"""
|
|
72
|
+
ctx.ensure_object(dict)
|
|
73
|
+
ctx.obj["json"] = json_mode
|
|
74
|
+
|
|
75
|
+
if ctx.invoked_subcommand is None:
|
|
76
|
+
# Enter REPL mode
|
|
77
|
+
_run_repl(ctx, json_mode)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _run_repl(ctx, json_mode: bool):
|
|
81
|
+
"""Run interactive REPL mode."""
|
|
82
|
+
_skin.print_banner()
|
|
83
|
+
|
|
84
|
+
if not json_mode:
|
|
85
|
+
_skin.info("Type 'help' for commands, 'quit' to exit.")
|
|
86
|
+
print()
|
|
87
|
+
|
|
88
|
+
pt_session = _skin.create_prompt_session()
|
|
89
|
+
|
|
90
|
+
while True:
|
|
91
|
+
try:
|
|
92
|
+
line = _skin.get_input(pt_session)
|
|
93
|
+
except (EOFError, KeyboardInterrupt):
|
|
94
|
+
_skin.print_goodbye()
|
|
95
|
+
break
|
|
96
|
+
|
|
97
|
+
if not line:
|
|
98
|
+
continue
|
|
99
|
+
|
|
100
|
+
cmd = line.strip().lower()
|
|
101
|
+
if cmd in ("quit", "exit", "q"):
|
|
102
|
+
_skin.print_goodbye()
|
|
103
|
+
break
|
|
104
|
+
if cmd in ("help", "?", "h"):
|
|
105
|
+
_print_repl_help()
|
|
106
|
+
continue
|
|
107
|
+
|
|
108
|
+
try:
|
|
109
|
+
args = shlex.split(line)
|
|
110
|
+
except ValueError as exc:
|
|
111
|
+
_skin.error(f"Parse error: {exc}")
|
|
112
|
+
continue
|
|
113
|
+
|
|
114
|
+
# Preserve --json flag
|
|
115
|
+
repl_args = ["--json"] + args if json_mode else args
|
|
116
|
+
|
|
117
|
+
try:
|
|
118
|
+
cli.main(args=repl_args, standalone_mode=False)
|
|
119
|
+
except SystemExit:
|
|
120
|
+
pass
|
|
121
|
+
except click.UsageError as exc:
|
|
122
|
+
_skin.error(str(exc))
|
|
123
|
+
except Exception as exc:
|
|
124
|
+
if json_mode and isinstance(exc, AmazonError):
|
|
125
|
+
import json as _json
|
|
126
|
+
|
|
127
|
+
click.echo(_json.dumps(exc.to_dict()))
|
|
128
|
+
else:
|
|
129
|
+
_skin.error(str(exc))
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# Register subcommands
|
|
133
|
+
cli.add_command(search)
|
|
134
|
+
cli.add_command(suggest)
|
|
135
|
+
cli.add_command(product)
|
|
136
|
+
cli.add_command(bestsellers)
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def main():
|
|
140
|
+
"""Entry point for cli-web-amazon."""
|
|
141
|
+
cli()
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# MCP server mode — exposes every command as an MCP tool over stdio.
|
|
145
|
+
# Canonical adapter: cli-web-core/cli_web_core/mcp_server.py (vendored copy).
|
|
146
|
+
from cli_web.amazon import __version__ as _pkg_version # noqa: E402
|
|
147
|
+
from cli_web.amazon.utils.doctor import register_doctor_command # noqa: E402
|
|
148
|
+
from cli_web.amazon.utils.mcp_server import register_mcp_command # noqa: E402
|
|
149
|
+
|
|
150
|
+
register_mcp_command(cli, app_name="amazon", version=_pkg_version)
|
|
151
|
+
register_doctor_command(cli, app_name="amazon", pkg="amazon")
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
if __name__ == "__main__":
|
|
155
|
+
main()
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""CLI command groups for cli-web-amazon."""
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Best sellers commands for cli-web-amazon."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from ..core.client import AmazonClient
|
|
6
|
+
from ..utils.helpers import handle_errors, print_json
|
|
7
|
+
from ..utils.output import print_bestsellers
|
|
8
|
+
|
|
9
|
+
COMMON_CATEGORIES = [
|
|
10
|
+
"electronics",
|
|
11
|
+
"books",
|
|
12
|
+
"toys-and-games",
|
|
13
|
+
"music",
|
|
14
|
+
"video-games",
|
|
15
|
+
"home-garden",
|
|
16
|
+
"clothing-shoes-jewelry",
|
|
17
|
+
"sports-outdoors",
|
|
18
|
+
"kitchen",
|
|
19
|
+
"office-products",
|
|
20
|
+
"pet-supplies",
|
|
21
|
+
"beauty",
|
|
22
|
+
"health-household",
|
|
23
|
+
"automotive",
|
|
24
|
+
"tools-home-improvement",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@click.command("bestsellers")
|
|
29
|
+
@click.argument("category", default="electronics")
|
|
30
|
+
@click.option(
|
|
31
|
+
"--page", type=int, default=1, show_default=True, help="Page number (each page has ~50 items)."
|
|
32
|
+
)
|
|
33
|
+
@click.option("--json", "use_json", is_flag=True, default=False, help="Output as JSON.")
|
|
34
|
+
def bestsellers(category, page, use_json):
|
|
35
|
+
"""Browse Amazon Best Sellers by category.
|
|
36
|
+
|
|
37
|
+
CATEGORY defaults to 'electronics'. Other common values:
|
|
38
|
+
books, toys-and-games, music, video-games, home-garden,
|
|
39
|
+
clothing-shoes-jewelry, sports-outdoors, kitchen, beauty
|
|
40
|
+
|
|
41
|
+
Examples:
|
|
42
|
+
cli-web-amazon bestsellers
|
|
43
|
+
cli-web-amazon bestsellers books
|
|
44
|
+
cli-web-amazon bestsellers electronics --page 2
|
|
45
|
+
cli-web-amazon bestsellers toys-and-games --json
|
|
46
|
+
"""
|
|
47
|
+
with handle_errors(json_mode=use_json):
|
|
48
|
+
with AmazonClient() as client:
|
|
49
|
+
items = client.get_bestsellers(category=category, page=page)
|
|
50
|
+
|
|
51
|
+
if use_json:
|
|
52
|
+
print_json([i.to_dict() for i in items])
|
|
53
|
+
else:
|
|
54
|
+
if not items:
|
|
55
|
+
click.echo(
|
|
56
|
+
f"No best sellers found for category '{category}'.\n"
|
|
57
|
+
f"Try one of: {', '.join(COMMON_CATEGORIES[:5])}"
|
|
58
|
+
)
|
|
59
|
+
else:
|
|
60
|
+
print_bestsellers(items, category=category)
|
|
61
|
+
click.echo(f"\n{len(items)} items. Use --page to see more.")
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Product commands for cli-web-amazon."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from ..core.client import AmazonClient
|
|
6
|
+
from ..utils.helpers import handle_errors, print_json
|
|
7
|
+
from ..utils.output import print_product
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.group("product")
|
|
11
|
+
def product():
|
|
12
|
+
"""Amazon product operations."""
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@product.command("get")
|
|
17
|
+
@click.argument("asin")
|
|
18
|
+
@click.option("--json", "use_json", is_flag=True, default=False, help="Output as JSON.")
|
|
19
|
+
def get_product(asin, use_json):
|
|
20
|
+
"""Get product details by ASIN.
|
|
21
|
+
|
|
22
|
+
ASIN is Amazon's Standard Identification Number (e.g., B0GRZ78683).
|
|
23
|
+
|
|
24
|
+
Examples:
|
|
25
|
+
cli-web-amazon product get B0GRZ78683
|
|
26
|
+
cli-web-amazon product get B087JWTWF9 --json
|
|
27
|
+
"""
|
|
28
|
+
with handle_errors(json_mode=use_json):
|
|
29
|
+
asin = asin.upper().strip()
|
|
30
|
+
with AmazonClient() as client:
|
|
31
|
+
p = client.get_product(asin)
|
|
32
|
+
|
|
33
|
+
if use_json:
|
|
34
|
+
print_json(p.to_dict())
|
|
35
|
+
else:
|
|
36
|
+
print_product(p)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Search commands for cli-web-amazon."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from ..core.client import AmazonClient
|
|
6
|
+
from ..utils.helpers import handle_errors, print_json
|
|
7
|
+
from ..utils.output import print_search_results
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.command("search")
|
|
11
|
+
@click.argument("query")
|
|
12
|
+
@click.option("--page", type=int, default=1, show_default=True, help="Page number of results.")
|
|
13
|
+
@click.option(
|
|
14
|
+
"--dept",
|
|
15
|
+
"--department",
|
|
16
|
+
"department",
|
|
17
|
+
default=None,
|
|
18
|
+
help="Department filter (e.g., 'electronics', 'books').",
|
|
19
|
+
)
|
|
20
|
+
@click.option("--json", "use_json", is_flag=True, default=False, help="Output as JSON.")
|
|
21
|
+
def search(query, page, department, use_json):
|
|
22
|
+
"""Search Amazon products by keyword.
|
|
23
|
+
|
|
24
|
+
Returns product cards with ASIN, title, price, and rating.
|
|
25
|
+
|
|
26
|
+
Examples:
|
|
27
|
+
cli-web-amazon search laptop
|
|
28
|
+
cli-web-amazon search "wireless headphones" --page 2
|
|
29
|
+
cli-web-amazon search camera --dept electronics
|
|
30
|
+
"""
|
|
31
|
+
with handle_errors(json_mode=use_json):
|
|
32
|
+
with AmazonClient() as client:
|
|
33
|
+
results = client.search(query, page=page, department=department)
|
|
34
|
+
|
|
35
|
+
if use_json:
|
|
36
|
+
print_json([r.to_dict() for r in results])
|
|
37
|
+
else:
|
|
38
|
+
if not results:
|
|
39
|
+
click.echo(f"No results found for '{query}'.")
|
|
40
|
+
else:
|
|
41
|
+
title = f"Search: {query}"
|
|
42
|
+
if page > 1:
|
|
43
|
+
title += f" (page {page})"
|
|
44
|
+
print_search_results(results, title=title)
|
|
45
|
+
click.echo(f"\n{len(results)} results. Use --page to see more.")
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Autocomplete suggestion commands for cli-web-amazon."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
|
|
5
|
+
from ..core.client import AmazonClient
|
|
6
|
+
from ..utils.helpers import handle_errors, print_json
|
|
7
|
+
from ..utils.output import print_suggestions
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.command("suggest")
|
|
11
|
+
@click.argument("query")
|
|
12
|
+
@click.option(
|
|
13
|
+
"--limit",
|
|
14
|
+
type=int,
|
|
15
|
+
default=11,
|
|
16
|
+
show_default=True,
|
|
17
|
+
help="Maximum number of suggestions to return.",
|
|
18
|
+
)
|
|
19
|
+
@click.option("--json", "use_json", is_flag=True, default=False, help="Output as JSON.")
|
|
20
|
+
def suggest(query, limit, use_json):
|
|
21
|
+
"""Get autocomplete suggestions for a search query.
|
|
22
|
+
|
|
23
|
+
Example: cli-web-amazon suggest laptop
|
|
24
|
+
"""
|
|
25
|
+
with handle_errors(json_mode=use_json):
|
|
26
|
+
with AmazonClient() as client:
|
|
27
|
+
results = client.get_suggestions(query, limit=limit)
|
|
28
|
+
|
|
29
|
+
if use_json:
|
|
30
|
+
print_json([s.to_dict() for s in results])
|
|
31
|
+
else:
|
|
32
|
+
if not results:
|
|
33
|
+
click.echo(f"No suggestions for '{query}'.")
|
|
34
|
+
else:
|
|
35
|
+
click.echo(f"Suggestions for '{query}':")
|
|
36
|
+
print_suggestions(results)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Core modules for cli-web-amazon."""
|