amazon-sp-cli 0.1.4__tar.gz → 0.1.5__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.
- {amazon_sp_cli-0.1.4/amazon_sp_cli.egg-info → amazon_sp_cli-0.1.5}/PKG-INFO +1 -1
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/amazon_sp_cli/auth.py +5 -1
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/amazon_sp_cli/main.py +20 -8
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5/amazon_sp_cli.egg-info}/PKG-INFO +1 -1
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/setup.py +1 -1
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/LICENSE +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/MANIFEST.in +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/README.md +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/amazon_sp_cli/__init__.py +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/amazon_sp_cli/__main__.py +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/amazon_sp_cli/client.py +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/amazon_sp_cli.egg-info/SOURCES.txt +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/amazon_sp_cli.egg-info/dependency_links.txt +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/amazon_sp_cli.egg-info/entry_points.txt +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/amazon_sp_cli.egg-info/requires.txt +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/amazon_sp_cli.egg-info/top_level.txt +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/pyproject.toml +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/setup.cfg +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/tests/__init__.py +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/tests/test_auth.py +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/tests/test_client.py +0 -0
- {amazon_sp_cli-0.1.4 → amazon_sp_cli-0.1.5}/tests/test_sale_price.py +0 -0
|
@@ -4,6 +4,7 @@ import json
|
|
|
4
4
|
import os
|
|
5
5
|
import time
|
|
6
6
|
from pathlib import Path
|
|
7
|
+
from typing import Optional
|
|
7
8
|
|
|
8
9
|
import requests
|
|
9
10
|
import yaml
|
|
@@ -20,11 +21,14 @@ class SPAPIAuth:
|
|
|
20
21
|
self.credentials = self._load_credentials(credentials_path)
|
|
21
22
|
self._ensure_cache_dir()
|
|
22
23
|
|
|
23
|
-
def _load_credentials(self, path: str = None) -> dict:
|
|
24
|
+
def _load_credentials(self, path: str = None) -> Optional[dict]:
|
|
24
25
|
"""Load credentials from YAML file."""
|
|
25
26
|
if path is None:
|
|
26
27
|
path = Path.home() / ".config" / "amazon-sp-cli" / "credentials.yml"
|
|
27
28
|
|
|
29
|
+
if not Path(path).exists():
|
|
30
|
+
return None
|
|
31
|
+
|
|
28
32
|
with open(path, "r") as f:
|
|
29
33
|
config = yaml.safe_load(f)
|
|
30
34
|
|
|
@@ -55,6 +55,18 @@ def _check_path():
|
|
|
55
55
|
print("", file=sys.stderr)
|
|
56
56
|
|
|
57
57
|
|
|
58
|
+
def _ensure_auth_client(ctx):
|
|
59
|
+
"""Lazily create auth and client if not already present."""
|
|
60
|
+
if "client" not in ctx.obj:
|
|
61
|
+
auth = SPAPIAuth(ctx.obj.get("credentials_path"))
|
|
62
|
+
if auth.credentials is None:
|
|
63
|
+
click.echo("Error: No credentials found. Run 'amz-sp auth setup' first.", err=True)
|
|
64
|
+
raise click.Abort()
|
|
65
|
+
ctx.obj["auth"] = auth
|
|
66
|
+
ctx.obj["client"] = SPAPIClient(auth)
|
|
67
|
+
return ctx.obj["auth"], ctx.obj["client"]
|
|
68
|
+
|
|
69
|
+
|
|
58
70
|
@click.group()
|
|
59
71
|
@click.option("--credentials", "-c", help="Path to credentials YAML file")
|
|
60
72
|
@click.pass_context
|
|
@@ -62,8 +74,7 @@ def cli(ctx, credentials):
|
|
|
62
74
|
"""Amazon SP-API CLI - Manage listings, pricing, inventory, and more."""
|
|
63
75
|
_check_path()
|
|
64
76
|
ctx.ensure_object(dict)
|
|
65
|
-
ctx.obj["
|
|
66
|
-
ctx.obj["client"] = SPAPIClient(ctx.obj["auth"])
|
|
77
|
+
ctx.obj["credentials_path"] = credentials
|
|
67
78
|
|
|
68
79
|
|
|
69
80
|
@cli.group()
|
|
@@ -187,7 +198,7 @@ def auth_show(ctx, path):
|
|
|
187
198
|
@click.pass_context
|
|
188
199
|
def get_price(ctx, sku):
|
|
189
200
|
"""Get current price for a SKU."""
|
|
190
|
-
client = ctx
|
|
201
|
+
_, client = _ensure_auth_client(ctx)
|
|
191
202
|
try:
|
|
192
203
|
response = client.get_listing(sku)
|
|
193
204
|
attributes = response.get("attributes", {})
|
|
@@ -213,7 +224,7 @@ def get_price(ctx, sku):
|
|
|
213
224
|
@click.pass_context
|
|
214
225
|
def set_price(ctx, sku, price, dry_run):
|
|
215
226
|
"""Set price for a SKU."""
|
|
216
|
-
client = ctx
|
|
227
|
+
_, client = _ensure_auth_client(ctx)
|
|
217
228
|
try:
|
|
218
229
|
mode = "VALIDATION_PREVIEW" if dry_run else None
|
|
219
230
|
response = client.update_price(sku, price, mode)
|
|
@@ -238,7 +249,7 @@ def set_price(ctx, sku, price, dry_run):
|
|
|
238
249
|
@click.pass_context
|
|
239
250
|
def create_discount(ctx, sku, percent, all_variations):
|
|
240
251
|
"""Create discount for a SKU."""
|
|
241
|
-
client = ctx
|
|
252
|
+
_, client = _ensure_auth_client(ctx)
|
|
242
253
|
|
|
243
254
|
try:
|
|
244
255
|
if all_variations:
|
|
@@ -337,7 +348,7 @@ def sale_price(
|
|
|
337
348
|
amz-sp sale-price PAW2603190101 5 --type fixed
|
|
338
349
|
amz-sp sale-price PAW2603190101 15 --start-date 2026-05-01 --end-date 2026-05-31
|
|
339
350
|
"""
|
|
340
|
-
client = ctx
|
|
351
|
+
_, client = _ensure_auth_client(ctx)
|
|
341
352
|
|
|
342
353
|
try:
|
|
343
354
|
# Get current listing info
|
|
@@ -435,7 +446,7 @@ def sale_price(
|
|
|
435
446
|
@click.pass_context
|
|
436
447
|
def check_competitors(ctx, asin):
|
|
437
448
|
"""Check competitor pricing for an ASIN."""
|
|
438
|
-
client = ctx
|
|
449
|
+
_, client = _ensure_auth_client(ctx)
|
|
439
450
|
try:
|
|
440
451
|
response = client.get_catalog_item(asin)
|
|
441
452
|
attributes = response.get("attributes", {})
|
|
@@ -457,7 +468,8 @@ def check_competitors(ctx, asin):
|
|
|
457
468
|
@click.pass_context
|
|
458
469
|
def invalidate(ctx):
|
|
459
470
|
"""Invalidate cached access token."""
|
|
460
|
-
|
|
471
|
+
auth, _ = _ensure_auth_client(ctx)
|
|
472
|
+
auth.invalidate()
|
|
461
473
|
|
|
462
474
|
|
|
463
475
|
if __name__ == "__main__":
|
|
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
|