amazon-sp-cli 0.3.0__tar.gz → 0.3.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.
Files changed (36) hide show
  1. {amazon_sp_cli-0.3.0/amazon_sp_cli.egg-info → amazon_sp_cli-0.3.2}/PKG-INFO +1 -1
  2. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/__init__.py +1 -1
  3. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/client.py +9 -10
  4. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/commands/auth.py +1 -1
  5. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/commands/listings.py +16 -0
  6. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/main.py +0 -2
  7. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2/amazon_sp_cli.egg-info}/PKG-INFO +1 -1
  8. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli.egg-info/SOURCES.txt +0 -2
  9. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/tests/test_listings.py +84 -0
  10. amazon_sp_cli-0.3.0/amazon_sp_cli/commands/inventory.py +0 -31
  11. amazon_sp_cli-0.3.0/tests/test_inventory.py +0 -118
  12. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/LICENSE +0 -0
  13. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/MANIFEST.in +0 -0
  14. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/README.md +0 -0
  15. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/__main__.py +0 -0
  16. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/auth.py +0 -0
  17. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/cli.py +0 -0
  18. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/commands/__init__.py +0 -0
  19. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/commands/a_plus.py +0 -0
  20. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/commands/pricing.py +0 -0
  21. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/commands/update.py +0 -0
  22. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/models/__init__.py +0 -0
  23. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli/models/a_plus.py +0 -0
  24. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli.egg-info/dependency_links.txt +0 -0
  25. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli.egg-info/entry_points.txt +0 -0
  26. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli.egg-info/requires.txt +0 -0
  27. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/amazon_sp_cli.egg-info/top_level.txt +0 -0
  28. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/pyproject.toml +0 -0
  29. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/setup.cfg +0 -0
  30. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/setup.py +0 -0
  31. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/tests/__init__.py +0 -0
  32. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/tests/test_a_plus.py +0 -0
  33. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/tests/test_auth.py +0 -0
  34. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/tests/test_client.py +0 -0
  35. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/tests/test_pricing.py +0 -0
  36. {amazon_sp_cli-0.3.0 → amazon_sp_cli-0.3.2}/tests/test_update.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amazon-sp-cli
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: CLI tool for Amazon Selling Partner API (SP-API) operations
5
5
  Home-page: https://github.com/stellaraether/amazon-sp-cli
6
6
  Author: Lunan Li
@@ -1,3 +1,3 @@
1
1
  # Amazon SP-API CLI tool
2
2
 
3
- __version__ = "0.3.0"
3
+ __version__ = "0.3.2"
@@ -140,19 +140,18 @@ class SPAPIClient:
140
140
 
141
141
  return self.request("PUT", path, data)
142
142
 
143
- def get_fba_inventory(self, seller_skus: str = None, next_token: str = None, details: bool = True) -> dict:
144
- """Get FBA inventory summaries."""
145
- path = "/fba/inventory/v1/getInventorySummaries"
143
+ def search_listings_items(self, page_size: int = None, page_token: str = None, included_data: str = None) -> dict:
144
+ """Search listings items for the seller."""
145
+ path = f"/listings/2021-08-01/items/{self.seller_id}"
146
146
  params = {
147
- "details": "true" if details else "false",
148
- "granularityType": "Marketplace",
149
- "granularityId": self.marketplace_id,
150
147
  "marketplaceIds": self.marketplace_id,
151
148
  }
152
- if seller_skus:
153
- params["sellerSkus"] = seller_skus
154
- if next_token:
155
- params["nextToken"] = next_token
149
+ if page_size is not None:
150
+ params["pageSize"] = str(page_size)
151
+ if page_token:
152
+ params["pageToken"] = page_token
153
+ if included_data:
154
+ params["includedData"] = included_data
156
155
  path += "?" + urlencode(params)
157
156
  return self.request("GET", path)
158
157
 
@@ -24,7 +24,7 @@ def register_auth_commands(cli_group):
24
24
  @click.option("--client-secret", help="Client secret")
25
25
  @click.option("--aws-access-key-id", help="AWS Access Key ID")
26
26
  @click.option("--aws-secret-access-key", help="AWS Secret Access Key")
27
- @click.option("--seller-id", default="A2GKV2AN9F8YG3", help="Seller ID")
27
+ @click.option("--seller-id", help="Seller ID")
28
28
  @click.option("--marketplace-id", default="ATVPDKIKX0DER", help="Marketplace ID")
29
29
  @click.pass_context
30
30
  def auth_setup(
@@ -180,6 +180,22 @@ def register_listings_commands(cli_group, ensure_auth_client):
180
180
  else:
181
181
  click.echo(json.dumps(response, indent=2))
182
182
 
183
+ @cli_group.command("list-recent-listings")
184
+ @click.option("--page-size", type=int, default=10, help="Number of items per page (max 20)")
185
+ @click.option("--page-token", help="Pagination token from a previous response")
186
+ @click.option("--included-data", default="summaries", help="Comma-separated included data sets")
187
+ @click.pass_context
188
+ @handle_errors
189
+ def list_recent_listings(ctx, page_size, page_token, included_data):
190
+ """List recent listings for the seller."""
191
+ _, client = ensure_auth_client(ctx)
192
+ response = client.search_listings_items(
193
+ page_size=page_size,
194
+ page_token=page_token,
195
+ included_data=included_data,
196
+ )
197
+ click.echo(json.dumps(response, indent=2))
198
+
183
199
  @cli_group.command()
184
200
  @click.argument("sku")
185
201
  @click.pass_context
@@ -3,7 +3,6 @@
3
3
  from .cli import _ensure_auth_client, cli
4
4
  from .commands.a_plus import register_a_plus_commands
5
5
  from .commands.auth import register_auth_commands
6
- from .commands.inventory import register_inventory_commands
7
6
  from .commands.listings import register_listings_commands
8
7
  from .commands.pricing import register_pricing_commands
9
8
  from .commands.update import register_update_commands
@@ -12,5 +11,4 @@ register_auth_commands(cli)
12
11
  register_listings_commands(cli, _ensure_auth_client)
13
12
  register_pricing_commands(cli, _ensure_auth_client)
14
13
  register_a_plus_commands(cli, _ensure_auth_client)
15
- register_inventory_commands(cli, _ensure_auth_client)
16
14
  register_update_commands(cli)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amazon-sp-cli
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: CLI tool for Amazon Selling Partner API (SP-API) operations
5
5
  Home-page: https://github.com/stellaraether/amazon-sp-cli
6
6
  Author: Lunan Li
@@ -18,7 +18,6 @@ amazon_sp_cli.egg-info/top_level.txt
18
18
  amazon_sp_cli/commands/__init__.py
19
19
  amazon_sp_cli/commands/a_plus.py
20
20
  amazon_sp_cli/commands/auth.py
21
- amazon_sp_cli/commands/inventory.py
22
21
  amazon_sp_cli/commands/listings.py
23
22
  amazon_sp_cli/commands/pricing.py
24
23
  amazon_sp_cli/commands/update.py
@@ -28,7 +27,6 @@ tests/__init__.py
28
27
  tests/test_a_plus.py
29
28
  tests/test_auth.py
30
29
  tests/test_client.py
31
- tests/test_inventory.py
32
30
  tests/test_listings.py
33
31
  tests/test_pricing.py
34
32
  tests/test_update.py
@@ -364,6 +364,90 @@ class TestUpdateListing:
364
364
  assert call_args.kwargs["requirements"] == "LISTING_OFFER_ONLY"
365
365
 
366
366
 
367
+ class TestListRecentListings:
368
+ """Test list-recent-listings command."""
369
+
370
+ @pytest.fixture
371
+ def mock_search_response(self):
372
+ """Mock search listings response."""
373
+ return {
374
+ "items": [
375
+ {
376
+ "sku": "SKU-123",
377
+ "summaries": [{"status": ["ACTIVE"], "asin": "B09BBL8T4Z"}],
378
+ },
379
+ {
380
+ "sku": "SKU-456",
381
+ "summaries": [{"status": ["ACTIVE"], "asin": "B09BBL8T5Z"}],
382
+ },
383
+ ],
384
+ "pagination": {"nextToken": "token123"},
385
+ }
386
+
387
+ @pytest.fixture
388
+ def runner(self):
389
+ """Create Click test runner."""
390
+ return CliRunner()
391
+
392
+ @patch("amazon_sp_cli.cli.SPAPIAuth")
393
+ @patch("amazon_sp_cli.cli.SPAPIClient")
394
+ def test_list_recent_listings(self, mock_client_class, mock_auth_class, runner, mock_search_response):
395
+ """Test listing recent listings."""
396
+ mock_client = Mock()
397
+ mock_client.search_listings_items.return_value = mock_search_response
398
+ mock_client_class.return_value = mock_client
399
+
400
+ mock_auth = Mock()
401
+ mock_auth_class.return_value = mock_auth
402
+
403
+ result = runner.invoke(cli, ["list-recent-listings"])
404
+
405
+ assert result.exit_code == 0
406
+ output = json.loads(result.output)
407
+ assert len(output["items"]) == 2
408
+ assert output["items"][0]["sku"] == "SKU-123"
409
+ assert output["pagination"]["nextToken"] == "token123"
410
+
411
+ @patch("amazon_sp_cli.cli.SPAPIAuth")
412
+ @patch("amazon_sp_cli.cli.SPAPIClient")
413
+ def test_list_recent_listings_with_pagination(
414
+ self, mock_client_class, mock_auth_class, runner, mock_search_response
415
+ ):
416
+ """Test listing recent listings with page size and token."""
417
+ mock_client = Mock()
418
+ mock_client.search_listings_items.return_value = mock_search_response
419
+ mock_client_class.return_value = mock_client
420
+
421
+ mock_auth = Mock()
422
+ mock_auth_class.return_value = mock_auth
423
+
424
+ result = runner.invoke(cli, ["list-recent-listings", "--page-size", "5", "--page-token", "abc"])
425
+
426
+ assert result.exit_code == 0
427
+ mock_client.search_listings_items.assert_called_once_with(
428
+ page_size=5,
429
+ page_token="abc",
430
+ included_data="summaries",
431
+ )
432
+
433
+ @patch("amazon_sp_cli.cli.SPAPIAuth")
434
+ @patch("amazon_sp_cli.cli.SPAPIClient")
435
+ def test_list_recent_listings_empty(self, mock_client_class, mock_auth_class, runner):
436
+ """Test listing recent listings with no results."""
437
+ mock_client = Mock()
438
+ mock_client.search_listings_items.return_value = {"items": []}
439
+ mock_client_class.return_value = mock_client
440
+
441
+ mock_auth = Mock()
442
+ mock_auth_class.return_value = mock_auth
443
+
444
+ result = runner.invoke(cli, ["list-recent-listings"])
445
+
446
+ assert result.exit_code == 0
447
+ output = json.loads(result.output)
448
+ assert output["items"] == []
449
+
450
+
367
451
  class TestDeleteListing:
368
452
  """Test delete-listing command."""
369
453
 
@@ -1,31 +0,0 @@
1
- """Inventory commands."""
2
-
3
- import json
4
-
5
- import click
6
-
7
- from ..cli import handle_errors
8
-
9
-
10
- def register_inventory_commands(cli_group, ensure_auth_client):
11
- """Register inventory CLI commands."""
12
-
13
- @cli_group.command("list-fba-inventory")
14
- @click.option("--sku", help="Filter by specific SKU (comma-separated for multiple)")
15
- @click.option("--next-token", help="Pagination token from a previous response")
16
- @click.pass_context
17
- @handle_errors
18
- def list_fba_inventory(ctx, sku, next_token):
19
- """List FBA inventory summaries."""
20
- _, client = ensure_auth_client(ctx)
21
- response = client.get_fba_inventory(seller_skus=sku, next_token=next_token)
22
-
23
- payload = response.get("payload", {})
24
- summaries = payload.get("inventorySummaries", [])
25
- result = {"inventory": summaries}
26
-
27
- pagination = payload.get("pagination", {})
28
- if pagination.get("nextToken"):
29
- result["nextToken"] = pagination["nextToken"]
30
-
31
- click.echo(json.dumps(result, indent=2))
@@ -1,118 +0,0 @@
1
- """Tests for inventory commands."""
2
-
3
- import json
4
- from unittest.mock import Mock, patch
5
-
6
- import pytest
7
- from click.testing import CliRunner
8
-
9
- from amazon_sp_cli.main import cli
10
-
11
-
12
- class TestListFbaInventory:
13
- """Test list-fba-inventory command."""
14
-
15
- @pytest.fixture
16
- def runner(self):
17
- """Create Click test runner."""
18
- return CliRunner()
19
-
20
- @pytest.fixture
21
- def mock_inventory_response(self):
22
- """Mock FBA inventory response."""
23
- return {
24
- "payload": {
25
- "inventorySummaries": [
26
- {
27
- "sellerSku": "SKU-123",
28
- "asin": "B09BBL8T4Z",
29
- "fnSku": "X123456789",
30
- "productName": "Test Product",
31
- "condition": "NewItem",
32
- "inventoryDetails": {
33
- "fulfillableQuantity": 10,
34
- "inboundWorkingQuantity": 5,
35
- },
36
- }
37
- ],
38
- "pagination": {"nextToken": "token123"},
39
- }
40
- }
41
-
42
- @patch("amazon_sp_cli.cli.SPAPIAuth")
43
- @patch("amazon_sp_cli.cli.SPAPIClient")
44
- def test_list_fba_inventory(self, mock_client_class, mock_auth_class, runner, mock_inventory_response):
45
- """Test listing FBA inventory."""
46
- mock_client = Mock()
47
- mock_client.get_fba_inventory.return_value = mock_inventory_response
48
- mock_client_class.return_value = mock_client
49
-
50
- mock_auth = Mock()
51
- mock_auth_class.return_value = mock_auth
52
-
53
- result = runner.invoke(cli, ["list-fba-inventory"])
54
-
55
- assert result.exit_code == 0
56
- # Strip PATH warning if present
57
- output_text = result.output
58
- if "{" in output_text:
59
- brace_idx = output_text.index("{")
60
- output_text = output_text[brace_idx:]
61
- output = json.loads(output_text)
62
- assert len(output["inventory"]) == 1
63
- assert output["inventory"][0]["sellerSku"] == "SKU-123"
64
- assert output["nextToken"] == "token123"
65
-
66
- @patch("amazon_sp_cli.cli.SPAPIAuth")
67
- @patch("amazon_sp_cli.cli.SPAPIClient")
68
- def test_list_fba_inventory_with_sku_filter(
69
- self, mock_client_class, mock_auth_class, runner, mock_inventory_response
70
- ):
71
- """Test listing FBA inventory filtered by SKU."""
72
- mock_client = Mock()
73
- mock_client.get_fba_inventory.return_value = mock_inventory_response
74
- mock_client_class.return_value = mock_client
75
-
76
- mock_auth = Mock()
77
- mock_auth_class.return_value = mock_auth
78
-
79
- result = runner.invoke(cli, ["list-fba-inventory", "--sku", "SKU-123,SKU-456"])
80
-
81
- assert result.exit_code == 0
82
- mock_client.get_fba_inventory.assert_called_once_with(seller_skus="SKU-123,SKU-456", next_token=None)
83
-
84
- @patch("amazon_sp_cli.cli.SPAPIAuth")
85
- @patch("amazon_sp_cli.cli.SPAPIClient")
86
- def test_list_fba_inventory_with_next_token(
87
- self, mock_client_class, mock_auth_class, runner, mock_inventory_response
88
- ):
89
- """Test listing FBA inventory with pagination token."""
90
- mock_client = Mock()
91
- mock_client.get_fba_inventory.return_value = mock_inventory_response
92
- mock_client_class.return_value = mock_client
93
-
94
- mock_auth = Mock()
95
- mock_auth_class.return_value = mock_auth
96
-
97
- result = runner.invoke(cli, ["list-fba-inventory", "--next-token", "token456"])
98
-
99
- assert result.exit_code == 0
100
- mock_client.get_fba_inventory.assert_called_once_with(seller_skus=None, next_token="token456")
101
-
102
- @patch("amazon_sp_cli.cli.SPAPIAuth")
103
- @patch("amazon_sp_cli.cli.SPAPIClient")
104
- def test_list_fba_inventory_empty(self, mock_client_class, mock_auth_class, runner):
105
- """Test listing FBA inventory with no results."""
106
- mock_client = Mock()
107
- mock_client.get_fba_inventory.return_value = {"payload": {"inventorySummaries": []}}
108
- mock_client_class.return_value = mock_client
109
-
110
- mock_auth = Mock()
111
- mock_auth_class.return_value = mock_auth
112
-
113
- result = runner.invoke(cli, ["list-fba-inventory"])
114
-
115
- assert result.exit_code == 0
116
- output = json.loads(result.output)
117
- assert output["inventory"] == []
118
- assert "nextToken" not in output
File without changes
File without changes
File without changes
File without changes
File without changes