plentymarkets-api-client 0.1.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 (35) hide show
  1. plentymarkets_api_client-0.1.2/.claude/CLAUDE.md +72 -0
  2. plentymarkets_api_client-0.1.2/.forgejo/workflows/release.yml +105 -0
  3. plentymarkets_api_client-0.1.2/.gitignore +10 -0
  4. plentymarkets_api_client-0.1.2/.pre-commit-config.yaml +6 -0
  5. plentymarkets_api_client-0.1.2/.python-version +1 -0
  6. plentymarkets_api_client-0.1.2/CHANGELOG.md +42 -0
  7. plentymarkets_api_client-0.1.2/LICENSE +21 -0
  8. plentymarkets_api_client-0.1.2/PKG-INFO +153 -0
  9. plentymarkets_api_client-0.1.2/README.md +99 -0
  10. plentymarkets_api_client-0.1.2/ROADMAP.md +60 -0
  11. plentymarkets_api_client-0.1.2/docs/superpowers/plans/2026-06-30-pyPlentyAPI-initial-implementation.md +2106 -0
  12. plentymarkets_api_client-0.1.2/docs/superpowers/plans/2026-06-30-pyPlentyAPI.md +2503 -0
  13. plentymarkets_api_client-0.1.2/docs/superpowers/specs/2026-06-30-pyPlentyAPI-design.md +164 -0
  14. plentymarkets_api_client-0.1.2/pyproject.toml +60 -0
  15. plentymarkets_api_client-0.1.2/scripts/bump_changelog.py +33 -0
  16. plentymarkets_api_client-0.1.2/src/plentymarkets/__init__.py +19 -0
  17. plentymarkets_api_client-0.1.2/src/plentymarkets/_exceptions.py +31 -0
  18. plentymarkets_api_client-0.1.2/src/plentymarkets/_session.py +240 -0
  19. plentymarkets_api_client-0.1.2/src/plentymarkets/_types.py +277 -0
  20. plentymarkets_api_client-0.1.2/src/plentymarkets/client.py +96 -0
  21. plentymarkets_api_client-0.1.2/src/plentymarkets/modules/__init__.py +0 -0
  22. plentymarkets_api_client-0.1.2/src/plentymarkets/modules/contacts.py +230 -0
  23. plentymarkets_api_client-0.1.2/src/plentymarkets/modules/items.py +179 -0
  24. plentymarkets_api_client-0.1.2/src/plentymarkets/modules/orders.py +203 -0
  25. plentymarkets_api_client-0.1.2/src/plentymarkets/modules/stock.py +119 -0
  26. plentymarkets_api_client-0.1.2/src/plentymarkets/py.typed +0 -0
  27. plentymarkets_api_client-0.1.2/tests/__init__.py +0 -0
  28. plentymarkets_api_client-0.1.2/tests/conftest.py +9 -0
  29. plentymarkets_api_client-0.1.2/tests/test_client.py +58 -0
  30. plentymarkets_api_client-0.1.2/tests/test_contacts.py +87 -0
  31. plentymarkets_api_client-0.1.2/tests/test_exceptions.py +32 -0
  32. plentymarkets_api_client-0.1.2/tests/test_items.py +87 -0
  33. plentymarkets_api_client-0.1.2/tests/test_orders.py +110 -0
  34. plentymarkets_api_client-0.1.2/tests/test_session.py +324 -0
  35. plentymarkets_api_client-0.1.2/tests/test_stock.py +78 -0
@@ -0,0 +1,72 @@
1
+ # pyPlentyAPI — Claude Guide
2
+
3
+ ## Project
4
+ Async Python client for the PlentyMarkets REST API. NOT PlentyBase.
5
+ Package name: `plentymarkets`. Entry point: `PlentyClient`.
6
+
7
+ ## API Docs
8
+ - REST API reference: https://developers.plentymarkets.com/en-gb/plentymarkets-rest-api/index.html
9
+ - OpenAPI spec (JSON): https://raw.githubusercontent.com/plentymarkets/api-doc/master/plentymarkets/openApiV3/openApiV3.json
10
+
11
+ ## Setup
12
+ ```bash
13
+ uv sync --extra dev
14
+ uv run pre-commit install --hook-type commit-msg
15
+ ```
16
+
17
+ ## Running tests
18
+ ```bash
19
+ uv run pytest # unit tests only
20
+ uv run pytest -m integration # requires live credentials
21
+ ```
22
+
23
+ ## Conventions
24
+ - Conventional commits enforced via commitizen (`feat:`, `fix:`, `docs:`, `chore:`, `test:`, `refactor:`)
25
+ - Google-style docstrings on ALL public methods; document every response dict key
26
+ - CHANGELOG.md: only ever write to `[Unreleased]` — never add a release section
27
+ - CHANGELOG.md: Group changes by module. Use the same prefix as in commit messages.
28
+ - Small focused commits, one logical change each
29
+ - **Branch workflow:** All changes must branch off `staging` and be merged back into `staging`. `main` is protected and only updated via merges from `staging`.
30
+
31
+ ## Package structure
32
+ ```
33
+ src/plentymarkets/
34
+ __init__.py # exports PlentyClient + all TypedDicts
35
+ client.py # PlentyClient
36
+ _session.py # HTTP session, auth lifecycle
37
+ _exceptions.py # exception hierarchy
38
+ _types.py # TypedDict payload definitions for all write operations
39
+ modules/
40
+ orders.py # OrdersModule → /rest/orders
41
+ items.py # ItemsModule → /rest/items
42
+ stock.py # StockModule → /rest/stock
43
+ contacts.py # ContactsModule → /rest/accounts/contacts
44
+ ```
45
+
46
+ ## TypedDicts
47
+ `_types.py` holds `TypedDict` definitions for every method that accepts a `data` dict.
48
+ Import them for IDE autocomplete and static type checking — at runtime they are plain dicts.
49
+
50
+ | TypedDict | Used by |
51
+ |---|---|
52
+ | `OrderCreatePayload` | `client.orders.create(data)` |
53
+ | `ItemCreatePayload` | `client.items.create(data)` |
54
+ | `ItemUpdatePayload` | `client.items.update(item_id, data)` |
55
+ | `StockCorrectionPayload` | `client.stock.correct(warehouse_id, data)` |
56
+ | `ContactCreatePayload` | `client.contacts.create(data)` |
57
+ | `ContactUpdatePayload` | `client.contacts.update(contact_id, data)` |
58
+
59
+ All six are exported from `plentymarkets` directly:
60
+ ```python
61
+ from plentymarkets import OrderCreatePayload, PlentyClient
62
+ ```
63
+
64
+ When adding a new module method that accepts a payload dict, add a matching TypedDict
65
+ to `_types.py` and export it from `__init__.py`.
66
+
67
+ ## Auth
68
+ POST /rest/login with username+password → accessToken + expiresIn (seconds).
69
+ Token sent as `Authorization: Bearer <token>` on every request.
70
+ Auto-refreshed when within 60 s of expiry. 401 mid-session → re-login once → retry.
71
+ ```
72
+ ```
@@ -0,0 +1,105 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ release:
10
+ runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: write
13
+
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+
17
+ - name: Install uv
18
+ run: |
19
+ curl -LsSf https://astral.sh/uv/install.sh | sh
20
+ echo "$HOME/.local/bin" >> $GITHUB_PATH
21
+
22
+ - name: Install dependencies
23
+ run: uv sync --extra dev
24
+
25
+ - name: Run tests
26
+ run: uv run pytest
27
+
28
+ - name: Extract version
29
+ id: version
30
+ run: |
31
+ VERSION=$(grep '^version' pyproject.toml | head -1 | cut -d'"' -f2)
32
+ echo "version=$VERSION" >> $GITHUB_OUTPUT
33
+ echo "tag=v$VERSION" >> $GITHUB_OUTPUT
34
+
35
+ - name: Build distribution
36
+ run: uv build
37
+
38
+ - name: Publish to PyPI
39
+ env:
40
+ UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
41
+ run: uv publish
42
+
43
+ - name: Extract changelog entry
44
+ id: changelog
45
+ run: |
46
+ python3 - "${{ steps.version.outputs.version }}" <<'EOF'
47
+ import re
48
+ import sys
49
+
50
+ version = sys.argv[1]
51
+ content = open("CHANGELOG.md").read()
52
+ pattern = rf"## \[{re.escape(version)}\][^\n]*\n(.*?)(?=\n## \[|\Z)"
53
+ match = re.search(pattern, content, re.DOTALL)
54
+ entry = match.group(1).strip() if match else ""
55
+ open("changelog_entry.md", "w").write(entry)
56
+ EOF
57
+
58
+ - name: Create release and upload artifacts
59
+ env:
60
+ GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
61
+ run: |
62
+ set -e
63
+ REPO="${{ github.repository }}"
64
+ TAG="${{ steps.version.outputs.tag }}"
65
+
66
+ STATUS=$(curl -s -o /dev/null -w "%{http_code}" \
67
+ -H "Authorization: token $GITEA_TOKEN" \
68
+ "https://codeberg.org/api/v1/repos/$REPO/releases/tags/$TAG")
69
+
70
+ if [ "$STATUS" != "200" ]; then
71
+ python3 - "$TAG" "${{ github.sha }}" <<'EOF' > release_payload.json
72
+ import json
73
+ import sys
74
+
75
+ tag, sha = sys.argv[1], sys.argv[2]
76
+ body = open("changelog_entry.md").read()
77
+ print(json.dumps({
78
+ "tag_name": tag,
79
+ "target_commitish": sha,
80
+ "name": tag,
81
+ "body": body,
82
+ "draft": False,
83
+ "prerelease": False,
84
+ }))
85
+ EOF
86
+
87
+ curl -X POST \
88
+ -H "Authorization: token $GITEA_TOKEN" \
89
+ -H "Content-Type: application/json" \
90
+ --data-binary @release_payload.json \
91
+ "https://codeberg.org/api/v1/repos/$REPO/releases"
92
+ fi
93
+
94
+ RELEASE_ID=$(curl -s \
95
+ -H "Authorization: token $GITEA_TOKEN" \
96
+ "https://codeberg.org/api/v1/repos/$REPO/releases/tags/$TAG" \
97
+ | python3 -c "import sys,json; print(json.load(sys.stdin)['id'])")
98
+
99
+ for file in dist/*; do
100
+ [ -f "$file" ] || continue
101
+ curl -X POST \
102
+ -H "Authorization: token $GITEA_TOKEN" \
103
+ -F "attachment=@$file" \
104
+ "https://codeberg.org/api/v1/repos/$REPO/releases/$RELEASE_ID/assets"
105
+ done
@@ -0,0 +1,10 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ .venv/
5
+ dist/
6
+ .uv/
7
+ uv.lock
8
+ .pytest_cache/
9
+ .ruff_cache/
10
+ .superpowers/
@@ -0,0 +1,6 @@
1
+ repos:
2
+ - repo: https://github.com/commitizen-tools/commitizen
3
+ rev: v3.29.1
4
+ hooks:
5
+ - id: commitizen
6
+ stages: [commit-msg]
@@ -0,0 +1 @@
1
+ 3.12
@@ -0,0 +1,42 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.2] - 2026-06-30
10
+
11
+ ### Changed
12
+ - `pyproject`: rename PyPI distribution from `plentymarkets` to `plentymarkets-api-client` — the import package stays `plentymarkets` (`from plentymarkets import PlentyClient`)
13
+ - `pyproject`: add full PyPI metadata — `readme`, `license`, `authors`, `keywords`, `classifiers`, `project.urls` (Homepage, Repository, Issues, Changelog)
14
+
15
+ ### Added
16
+ - `plentymarkets`: PEP 561 `py.typed` marker so downstream type checkers pick up the package's type hints
17
+
18
+ ## [0.1.1] - 2026-06-30
19
+
20
+ ### CI
21
+ - `release`: publish built distributions to PyPI via `uv publish` after the Codeberg release build ([`c450759`](https://codeberg.org/ZanderHammer/pyPlentyAPI/commit/c450759))
22
+ - `release`: use the matching `CHANGELOG.md` `## [VERSION]` section as the Codeberg release body instead of a generic link ([`07730aa`](https://codeberg.org/ZanderHammer/pyPlentyAPI/commit/07730aa))
23
+
24
+ ### Chore
25
+ - `commitizen`: add `scripts/bump_changelog.py` as a `pre_bump_hook` to version the `[Unreleased]` section into `## [VERSION] - DATE` automatically on `cz bump` ([`bc4728c`](https://codeberg.org/ZanderHammer/pyPlentyAPI/commit/bc4728c))
26
+
27
+ ## [0.1.0] - 2026-06-30
28
+
29
+ ### Added
30
+ - Exception hierarchy: `PlentyError`, `AuthError`, `NotFoundError`, `RateLimitError`, `ServerError`, `ConnectionError`
31
+ - `_Session`: async HTTP client with login, token auto-refresh, 401 re-login, and error mapping
32
+ - `PlentyClient`: async context manager with lazy `orders`, `items`, `stock`, `contacts` module properties
33
+ - `OrdersModule`: `get`, `list`, `create`, `update_status`, `paginate_orders` (`/rest/orders`)
34
+ - `ItemsModule`: `get`, `list`, `create`, `update`, `paginate_items` (`/rest/items`)
35
+ - `StockModule`: `get_by_warehouse`, `correct`, `paginate_stock` (`/rest/stock/warehouses`)
36
+ - `ContactsModule`: `get`, `list`, `create`, `update`, `paginate_contacts` (`/rest/accounts/contacts`)
37
+ - `_types`: `TypedDict` payload definitions for all write operations — `OrderCreatePayload`, `ItemCreatePayload`, `ItemUpdatePayload`, `StockCorrectionPayload`, `ContactCreatePayload`, `ContactUpdatePayload`; all exported from `plentymarkets` top-level
38
+ - `PlentyClient`, `OrdersModule`, `ItemsModule`, `StockModule`, `ContactsModule`: `__repr__` for readable debug output ([`5ad0e94`](https://codeberg.org/ZanderHammer/pyPlentyAPI/commit/5ad0e94))
39
+
40
+ ### Fixed
41
+ - `_session`: raise `ValueError` when `base_url` contains `/rest`, preventing a silent `JSONDecodeError` from doubled path segments ([`731ff44`](https://codeberg.org/ZanderHammer/pyPlentyAPI/commit/731ff44))
42
+ - All modules, `_session`: replace bare `dict` return annotations with `dict[str, Any]`, resolving `Unknown` type hints in Pylance ([`a47534d`](https://codeberg.org/ZanderHammer/pyPlentyAPI/commit/a47534d))
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Alexander Hammer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: plentymarkets-api-client
3
+ Version: 0.1.2
4
+ Summary: Async Python client for the PlentyMarkets REST API
5
+ Project-URL: Homepage, https://codeberg.org/ZanderHammer/pyPlentyAPI
6
+ Project-URL: Repository, https://codeberg.org/ZanderHammer/pyPlentyAPI
7
+ Project-URL: Issues, https://codeberg.org/ZanderHammer/pyPlentyAPI/issues
8
+ Project-URL: Changelog, https://codeberg.org/ZanderHammer/pyPlentyAPI/src/branch/main/CHANGELOG.md
9
+ Author-email: Alexander Hammer <acj259@gmail.com>
10
+ License: MIT License
11
+
12
+ Copyright (c) 2026 Alexander Hammer
13
+
14
+ Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ of this software and associated documentation files (the "Software"), to deal
16
+ in the Software without restriction, including without limitation the rights
17
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ copies of the Software, and to permit persons to whom the Software is
19
+ furnished to do so, subject to the following conditions:
20
+
21
+ The above copyright notice and this permission notice shall be included in all
22
+ copies or substantial portions of the Software.
23
+
24
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ SOFTWARE.
31
+ License-File: LICENSE
32
+ Keywords: async,ecommerce,httpx,plentymarkets,rest-api
33
+ Classifier: Development Status :: 3 - Alpha
34
+ Classifier: Intended Audience :: Developers
35
+ Classifier: License :: OSI Approved :: MIT License
36
+ Classifier: Operating System :: OS Independent
37
+ Classifier: Programming Language :: Python :: 3
38
+ Classifier: Programming Language :: Python :: 3.11
39
+ Classifier: Programming Language :: Python :: 3.12
40
+ Classifier: Programming Language :: Python :: 3.13
41
+ Classifier: Topic :: Internet :: WWW/HTTP
42
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
43
+ Classifier: Typing :: Typed
44
+ Requires-Python: >=3.11
45
+ Requires-Dist: httpx>=0.27
46
+ Provides-Extra: dev
47
+ Requires-Dist: commitizen>=3.29; extra == 'dev'
48
+ Requires-Dist: hatchling>=1.25; extra == 'dev'
49
+ Requires-Dist: pre-commit>=3.7; extra == 'dev'
50
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
51
+ Requires-Dist: pytest-httpx>=0.30; extra == 'dev'
52
+ Requires-Dist: pytest>=8.0; extra == 'dev'
53
+ Description-Content-Type: text/markdown
54
+
55
+ # pyPlentyAPI
56
+
57
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
58
+ [![Python: 3.11+](https://img.shields.io/badge/Python-3.11+-blue.svg)](https://www.python.org/downloads/)
59
+ [![UV: Sync](https://img.shields.io/badge/uv-sync-3178C6.svg?logo=python&logoColor=white)](https://github.com/astral-sh/uv)
60
+ [![Tests: Pytest](https://img.shields.io/badge/Tests-pytest-0A9EDC.svg?logo=pytest&logoColor=white)](https://docs.pytest.org/)
61
+
62
+ Async Python client for the [PlentyMarkets REST API](https://developers.plentymarkets.com/en-gb/plentymarkets-rest-api/index.html).
63
+
64
+ ## Features
65
+ - **Async-first**: Built on `httpx.AsyncClient` for high-performance async/await support.
66
+ - **Lazy-loaded modules**: Access `orders`, `items`, `stock`, and `contacts` as properties of `PlentyClient`.
67
+ - **Auto-refreshing auth**: Tokens are refreshed automatically when within 60 seconds of expiry.
68
+ - **Comprehensive error handling**: Custom exceptions for HTTP status codes (e.g., `NotFoundError`, `RateLimitError`).
69
+ - **Pagination support**: Async generators for iterating across all pages of results.
70
+ - **Type hints**: Full type annotations for IDE support and static analysis.
71
+
72
+ ## Installation
73
+ ```bash
74
+ pip install plentymarkets-api-client
75
+ ```
76
+
77
+ Or with `uv`:
78
+ ```bash
79
+ uv add plentymarkets-api-client
80
+ ```
81
+
82
+ ## Quickstart
83
+ ```python
84
+ import asyncio
85
+ from plentymarkets import PlentyClient
86
+
87
+ async def main():
88
+ async with PlentyClient(username="your_username", password="your_password") as client:
89
+ # Fetch an order by ID
90
+ order = await client.orders.get(123)
91
+ print(order)
92
+
93
+ # List all items (paginated)
94
+ async for item in client.items.paginate_items():
95
+ print(item)
96
+
97
+ asyncio.run(main())
98
+ ```
99
+
100
+ ## Modules
101
+ | Module | Description | Key Methods |
102
+ |-----------|--------------------------------------|-------------------------------------------------------------------------------------------------|
103
+ | **Orders** | Manage orders and order statuses. | `get()`, `list()`, `create()`, `update_status()`, `paginate_orders()` |
104
+ | **Items** | Manage items and item variants. | `get()`, `list()`, `create()`, `update()`, `paginate_items()` |
105
+ | **Stock** | Manage stock across warehouses. | `get_by_warehouse()`, `correct()`, `paginate_stock()` |
106
+ | **Contacts** | Manage customer and supplier data. | `get()`, `list()`, `create()`, `update()`, `paginate_contacts()` |
107
+
108
+ ## Authentication
109
+ 1. Initialize `PlentyClient` with your PlentyMarkets username and password.
110
+ 2. The client automatically logs in and manages the `accessToken` lifecycle.
111
+ 3. Tokens are sent as `Authorization: Bearer <token>` in all requests.
112
+ 4. If a 401 error occurs, the client attempts to re-login once before failing.
113
+
114
+ ## Error Handling
115
+ Custom exceptions are raised for HTTP errors:
116
+ - `AuthError`: 401 Unauthorized
117
+ - `NotFoundError`: 404 Not Found
118
+ - `RateLimitError`: 429 Too Many Requests
119
+ - `ServerError`: 5xx Server Errors
120
+ - `ConnectionError`: Network failures
121
+
122
+ Example:
123
+ ```python
124
+ try:
125
+ order = await client.orders.get(99999)
126
+ except plentymarkets.NotFoundError:
127
+ print("Order not found")
128
+ except plentymarkets.RateLimitError:
129
+ print("Rate limit exceeded")
130
+ ```
131
+
132
+ ## Pagination
133
+ Use async generators to iterate across all pages:
134
+ ```python
135
+ async for order in client.orders.paginate_orders():
136
+ print(order)
137
+ ```
138
+
139
+ ## Development
140
+ ### Setup
141
+ ```bash
142
+ uv sync --extra dev
143
+ uv run pre-commit install --hook-type commit-msg
144
+ ```
145
+
146
+ ### Running Tests
147
+ ```bash
148
+ uv run pytest # Unit tests
149
+ uv run pytest -m integration # Integration tests (requires live credentials)
150
+ ```
151
+
152
+ ## License
153
+ MIT
@@ -0,0 +1,99 @@
1
+ # pyPlentyAPI
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![Python: 3.11+](https://img.shields.io/badge/Python-3.11+-blue.svg)](https://www.python.org/downloads/)
5
+ [![UV: Sync](https://img.shields.io/badge/uv-sync-3178C6.svg?logo=python&logoColor=white)](https://github.com/astral-sh/uv)
6
+ [![Tests: Pytest](https://img.shields.io/badge/Tests-pytest-0A9EDC.svg?logo=pytest&logoColor=white)](https://docs.pytest.org/)
7
+
8
+ Async Python client for the [PlentyMarkets REST API](https://developers.plentymarkets.com/en-gb/plentymarkets-rest-api/index.html).
9
+
10
+ ## Features
11
+ - **Async-first**: Built on `httpx.AsyncClient` for high-performance async/await support.
12
+ - **Lazy-loaded modules**: Access `orders`, `items`, `stock`, and `contacts` as properties of `PlentyClient`.
13
+ - **Auto-refreshing auth**: Tokens are refreshed automatically when within 60 seconds of expiry.
14
+ - **Comprehensive error handling**: Custom exceptions for HTTP status codes (e.g., `NotFoundError`, `RateLimitError`).
15
+ - **Pagination support**: Async generators for iterating across all pages of results.
16
+ - **Type hints**: Full type annotations for IDE support and static analysis.
17
+
18
+ ## Installation
19
+ ```bash
20
+ pip install plentymarkets-api-client
21
+ ```
22
+
23
+ Or with `uv`:
24
+ ```bash
25
+ uv add plentymarkets-api-client
26
+ ```
27
+
28
+ ## Quickstart
29
+ ```python
30
+ import asyncio
31
+ from plentymarkets import PlentyClient
32
+
33
+ async def main():
34
+ async with PlentyClient(username="your_username", password="your_password") as client:
35
+ # Fetch an order by ID
36
+ order = await client.orders.get(123)
37
+ print(order)
38
+
39
+ # List all items (paginated)
40
+ async for item in client.items.paginate_items():
41
+ print(item)
42
+
43
+ asyncio.run(main())
44
+ ```
45
+
46
+ ## Modules
47
+ | Module | Description | Key Methods |
48
+ |-----------|--------------------------------------|-------------------------------------------------------------------------------------------------|
49
+ | **Orders** | Manage orders and order statuses. | `get()`, `list()`, `create()`, `update_status()`, `paginate_orders()` |
50
+ | **Items** | Manage items and item variants. | `get()`, `list()`, `create()`, `update()`, `paginate_items()` |
51
+ | **Stock** | Manage stock across warehouses. | `get_by_warehouse()`, `correct()`, `paginate_stock()` |
52
+ | **Contacts** | Manage customer and supplier data. | `get()`, `list()`, `create()`, `update()`, `paginate_contacts()` |
53
+
54
+ ## Authentication
55
+ 1. Initialize `PlentyClient` with your PlentyMarkets username and password.
56
+ 2. The client automatically logs in and manages the `accessToken` lifecycle.
57
+ 3. Tokens are sent as `Authorization: Bearer <token>` in all requests.
58
+ 4. If a 401 error occurs, the client attempts to re-login once before failing.
59
+
60
+ ## Error Handling
61
+ Custom exceptions are raised for HTTP errors:
62
+ - `AuthError`: 401 Unauthorized
63
+ - `NotFoundError`: 404 Not Found
64
+ - `RateLimitError`: 429 Too Many Requests
65
+ - `ServerError`: 5xx Server Errors
66
+ - `ConnectionError`: Network failures
67
+
68
+ Example:
69
+ ```python
70
+ try:
71
+ order = await client.orders.get(99999)
72
+ except plentymarkets.NotFoundError:
73
+ print("Order not found")
74
+ except plentymarkets.RateLimitError:
75
+ print("Rate limit exceeded")
76
+ ```
77
+
78
+ ## Pagination
79
+ Use async generators to iterate across all pages:
80
+ ```python
81
+ async for order in client.orders.paginate_orders():
82
+ print(order)
83
+ ```
84
+
85
+ ## Development
86
+ ### Setup
87
+ ```bash
88
+ uv sync --extra dev
89
+ uv run pre-commit install --hook-type commit-msg
90
+ ```
91
+
92
+ ### Running Tests
93
+ ```bash
94
+ uv run pytest # Unit tests
95
+ uv run pytest -m integration # Integration tests (requires live credentials)
96
+ ```
97
+
98
+ ## License
99
+ MIT
@@ -0,0 +1,60 @@
1
+ # Roadmap
2
+
3
+ All 53 modules available in the PlentyMarkets REST API. Modules marked **[core]** are in the
4
+ initial implementation scope. All others are planned for future incremental additions.
5
+
6
+ | API Tag | Description | Status |
7
+ |---|---|---|
8
+ | `Account` | Customer accounts and contacts — addresses, contact data, bank details | **[core]** |
9
+ | `Accounting` | VAT configurations, financial accounts, revenue bookings | planned |
10
+ | `AddressDesign` | Address label templates and print format settings | planned |
11
+ | `AuditLog` | Change history and audit trail for system actions | planned |
12
+ | `Authentication` | Login/logout and token management | internal (used by `_session.py`) |
13
+ | `Authorization` | User roles, permissions, and access rights | planned |
14
+ | `BI` | Business intelligence — reports and analytics data | planned |
15
+ | `Basket` | Shopping cart / basket management for webshop visitors | planned |
16
+ | `Batch` | Batch processing and bulk operations across resources | planned |
17
+ | `Blog` | Blog posts and categories published in the webshop | planned |
18
+ | `Board` | Task boards (Kanban-style) for internal team workflows | planned |
19
+ | `Boards` | Board management — creating and configuring boards | planned |
20
+ | `Catalog` | Data catalogues for flexible export/import field mappings | planned |
21
+ | `Category` | Product and content categories used in webshop and items | planned |
22
+ | `Cloud` | Cloud storage and file management | planned |
23
+ | `Comment` | Comments attachable to orders, contacts, and tickets | planned |
24
+ | `Configuration` | System-wide settings and global configuration values | planned |
25
+ | `Document` | Order documents — invoices, delivery notes, return slips | planned |
26
+ | `ElasticSync` | Data import/sync mappings (Data Exchange / ElasticSync) | planned |
27
+ | `Export` | Data export formats, fields, and export jobs | planned |
28
+ | `ExportSettings` | Settings and saved configurations for exports | planned |
29
+ | `Feedback` | Customer product reviews and ratings | planned |
30
+ | `Fulfillment` | Shipping labels, package tracking, shipping service providers | planned |
31
+ | `Item` | Product catalogue — items, variations, images, attributes, prices | **[core]** |
32
+ | `LegalInformation` | Legal texts — terms of service, privacy policy, cancellation rights | planned |
33
+ | `Listing` | eBay/marketplace listing templates and active listings | planned |
34
+ | `Log` | System log entries and error/debug logs | planned |
35
+ | `MailTemplates` | Email templates for automated system notifications | planned |
36
+ | `Market` | Marketplace integrations — Amazon, eBay, Otto, etc. | planned |
37
+ | `Messenger` | Internal messaging between system users | planned |
38
+ | `Newsletter` | Newsletter recipient lists and subscription management | planned |
39
+ | `Order` | Orders, order items, order properties, and status management | **[core]** |
40
+ | `OrderSummary` | Aggregated order statistics and revenue summaries | planned |
41
+ | `Payment` | Payments, payment methods, and booking payments to orders | planned |
42
+ | `Pim` | Product Information Management — PIM-specific item operations | planned |
43
+ | `PluginMultilingualism` | Plugin translation strings and multilingual content | planned |
44
+ | `PluginSet` | Plugin set management and deployment to clients | planned |
45
+ | `Plugins` | Plugin installation, configuration, and lifecycle | planned |
46
+ | `Property` | Item and contact properties — property groups and values | planned |
47
+ | `Returns` | Return orders, return reasons, and return processing | planned |
48
+ | `ShopBuilder` | Webshop layout and drag-and-drop page builder configuration | planned |
49
+ | `Stock` | Item stock levels, stock movements, and manual corrections | **[core]** |
50
+ | `StockManagement` | Warehouse-level stock redistribution and incoming goods | planned |
51
+ | `Sync` | Data synchronisation jobs and field mapping configuration | planned |
52
+ | `Tag` | Tags for labelling orders, contacts, variations, etc. | planned |
53
+ | `Ticket` | Support tickets and helpdesk case management | planned |
54
+ | `TicketMessage` | Messages and replies within support tickets | planned |
55
+ | `Todo` | Internal to-do tasks and user assignments | planned |
56
+ | `User` | System users, user accounts, and preferences | planned |
57
+ | `Warehouse` | Warehouse configuration, storage locations, rack management | planned |
58
+ | `Webstore` | Webshop settings, themes, plugins, and client configuration | planned |
59
+ | `Wizard` | Setup wizards for guided first-time configuration | planned |
60
+ | `plentyMarketplace` | plentyMarkets plugin marketplace integration | planned |