From 67b90338b8e877778d872ee11857a94a9e2a8e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Gro=C3=9F?= Date: Sun, 23 Mar 2025 21:27:38 +0000 Subject: [PATCH 01/17] Add logging to search extraction --- src/python_picnic_api2/helper.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/python_picnic_api2/helper.py b/src/python_picnic_api2/helper.py index 5954fe9..ab3c120 100644 --- a/src/python_picnic_api2/helper.py +++ b/src/python_picnic_api2/helper.py @@ -1,4 +1,5 @@ import json +import logging import re # prefix components: @@ -8,6 +9,8 @@ tee = "├── " last = "└── " +LOGGER = logging.getLogger(__name__) + IMAGE_SIZES = ["small", "medium", "regular", "large", "extra-large"] IMAGE_BASE_URL = "https://storefront-prod.nl.picnicinternational.com/static/images" @@ -89,18 +92,21 @@ def _extract_search_results(raw_results, max_items: int = 10): search_results = [] def find_articles(node): + LOGGER.debug(f"Searching for products in {node}") if len(search_results) >= max_items: return content = node.get("content", {}) if content.get("type") == "SELLING_UNIT_TILE" and "sellingUnit" in content: selling_unit = content["sellingUnit"] - sole_article_ids = SOLE_ARTICLE_ID_PATTERN.findall(json.dumps(node)) + sole_article_ids = SOLE_ARTICLE_ID_PATTERN.findall( + json.dumps(node)) sole_article_id = sole_article_ids[0] if sole_article_ids else None result_entry = { **selling_unit, "sole_article_id": sole_article_id, } + LOGGER.debug(f"Found article {result_entry}") search_results.append(result_entry) for child in node.get("children", []): @@ -109,7 +115,11 @@ def find_articles(node): if "child" in node: find_articles(node.get("child")) + LOGGER.debug(f"Leaving extraction for node {node}") + body = raw_results.get("body", {}) find_articles(body.get("child", {})) + LOGGER.debug(f"Found {len(search_results)} products after extraction") + return [{"items": search_results}] From 2714db9927638abfa596e14d83be22f7b196b08d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Gro=C3=9F?= Date: Tue, 25 Mar 2025 09:46:45 +0000 Subject: [PATCH 02/17] Reduce debug logging for product search --- src/python_picnic_api2/helper.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/python_picnic_api2/helper.py b/src/python_picnic_api2/helper.py index ab3c120..9bd08cb 100644 --- a/src/python_picnic_api2/helper.py +++ b/src/python_picnic_api2/helper.py @@ -91,16 +91,16 @@ def _extract_search_results(raw_results, max_items: int = 10): search""" search_results = [] + LOGGER.debug(f"Extracting search results from {raw_results}") + def find_articles(node): - LOGGER.debug(f"Searching for products in {node}") if len(search_results) >= max_items: return content = node.get("content", {}) if content.get("type") == "SELLING_UNIT_TILE" and "sellingUnit" in content: selling_unit = content["sellingUnit"] - sole_article_ids = SOLE_ARTICLE_ID_PATTERN.findall( - json.dumps(node)) + sole_article_ids = SOLE_ARTICLE_ID_PATTERN.findall(json.dumps(node)) sole_article_id = sole_article_ids[0] if sole_article_ids else None result_entry = { **selling_unit, @@ -115,11 +115,9 @@ def find_articles(node): if "child" in node: find_articles(node.get("child")) - LOGGER.debug(f"Leaving extraction for node {node}") - body = raw_results.get("body", {}) find_articles(body.get("child", {})) - LOGGER.debug(f"Found {len(search_results)} products after extraction") + LOGGER.debug(f"Found {len(search_results)}/{max_items} products after extraction") return [{"items": search_results}] From 60f5f428ad81419aef58fab0ff5131202209e8cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Gro=C3=9F?= Date: Tue, 25 Mar 2025 09:53:54 +0000 Subject: [PATCH 03/17] Bump version --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 99504af..dff975b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "python-picnic-api2" -version = "1.2.3" +version = "1.2.4" description = "" readme = "README.rst" license = {text = "Apache-2.0"} diff --git a/uv.lock b/uv.lock index 6337cb0..671d317 100644 --- a/uv.lock +++ b/uv.lock @@ -197,7 +197,7 @@ wheels = [ [[package]] name = "python-picnic-api2" -version = "1.2.2" +version = "1.2.4" source = { editable = "." } dependencies = [ { name = "requests" }, From 7a4479832d383bbc1512509f0c1a6c71ea8b094f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Gro=C3=9F?= Date: Mon, 21 Apr 2025 22:11:42 +0200 Subject: [PATCH 04/17] Enable dependabot for GHA and PIP --- .github/dependabot.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f33a02c..7a47c16 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -10,3 +10,11 @@ updates: directory: "/" schedule: interval: weekly + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: "weekly" From eb2806cc03e1c7f02460a3e99698d6e6318cb0e3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Apr 2025 20:12:17 +0000 Subject: [PATCH 05/17] Bump actions/setup-python from 2 to 5 Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2 to 5. - [Release notes](https://github.com/actions/setup-python/releases) - [Commits](https://github.com/actions/setup-python/compare/v2...v5) --- updated-dependencies: - dependency-name: actions/setup-python dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yaml | 2 +- .github/workflows/it.yaml | 2 +- .github/workflows/release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 21ee104..dcba5b9 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -20,7 +20,7 @@ jobs: - uses: actions/checkout@v2 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} diff --git a/.github/workflows/it.yaml b/.github/workflows/it.yaml index 5bb7468..c3b7718 100644 --- a/.github/workflows/it.yaml +++ b/.github/workflows/it.yaml @@ -14,7 +14,7 @@ jobs: - uses: actions/checkout@v2 - name: Set up Python 3.12 - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.12 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b4403ec..d6c7fae 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -7,7 +7,7 @@ jobs: - uses: actions/checkout@v2 - name: Set up Python 3.11 - uses: actions/setup-python@v2 + uses: actions/setup-python@v5 with: python-version: 3.11 From 33a850f2dec7ec3dfeb3b9668dd7b49d2b5a13b0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 21 Apr 2025 20:25:07 +0000 Subject: [PATCH 06/17] Bump actions/checkout from 2 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/ci.yaml | 2 +- .github/workflows/it.yaml | 2 +- .github/workflows/release.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index dcba5b9..9fd4373 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -17,7 +17,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v5 diff --git a/.github/workflows/it.yaml b/.github/workflows/it.yaml index c3b7718..3f201b4 100644 --- a/.github/workflows/it.yaml +++ b/.github/workflows/it.yaml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python 3.12 uses: actions/setup-python@v5 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d6c7fae..c5fa9a2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,7 +4,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Python 3.11 uses: actions/setup-python@v5 From 23d8783f631727d3d43e09a0666d22a0417beb4d Mon Sep 17 00:00:00 2001 From: Sven Bursch-Osewold Date: Mon, 21 Apr 2025 15:54:46 +0200 Subject: [PATCH 07/17] Ean Search added --- src/python_picnic_api2/client.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/python_picnic_api2/client.py b/src/python_picnic_api2/client.py index b1b04bd..8a82b1f 100644 --- a/src/python_picnic_api2/client.py +++ b/src/python_picnic_api2/client.py @@ -177,5 +177,30 @@ def print_categories(self, depth: int = 0): tree = "\n".join(_tree_generator(self.get_categories(depth=depth))) print(tree) + def get_product_from_gtin(self, etan: str, maxRedirects: int = 5): + + # Finds the product ID for a gtin/ean (barcode). + headers = ( + { + "x-picnic-agent": "30100;1.15.272-15295;", + "x-picnic-did": "3C417201548B2E3B", + } + ) + url = "https://picnic.app/" + self._country_code.lower() + "/qr/gtin/" + etan + while maxRedirects > 0: + if url == "http://picnic.app/nl/link/store/storefront": + # gtin unknown + return None + r = self.session.get(url, headers=headers, allow_redirects=False) + maxRedirects -= 1 + if ";id=" in r.url: + # found the product id + return r.url.split(";id=",1)[1] + if "Location" not in r.headers: + # product id not found but also no futher redirect + return None + url = r.headers["Location"] + return None + __all__ = ["PicnicAPI"] From a87006d36a946c4c62a7f2b9cdeb0a5be1118313 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Gro=C3=9F?= Date: Mon, 28 Apr 2025 19:21:38 +0000 Subject: [PATCH 08/17] Add tests for ean search --- integration_tests/test_client.py | 11 +++++++++++ src/python_picnic_api2/client.py | 31 +++++++++++-------------------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/integration_tests/test_client.py b/integration_tests/test_client.py index 43f7a2a..ffd2f29 100644 --- a/integration_tests/test_client.py +++ b/integration_tests/test_client.py @@ -56,6 +56,17 @@ def test_get_article_with_category_name(): picnic.get_article("s1018620", add_category_name=True) +def test_get_article_by_gtin(): + response = picnic.get_article_by_gtin("4311501044209") + assert response["id"] == "s1018620" + assert response["name"] == "Gut&Günstig H-Milch 3,5%" + + +def test_get_article_by_gtin_unknown(): + response = picnic.get_article_by_gtin("4311501040000") + assert response is None + + def test_get_cart(): response = picnic.get_cart() assert isinstance(response, dict) diff --git a/src/python_picnic_api2/client.py b/src/python_picnic_api2/client.py index 8a82b1f..8a02e72 100644 --- a/src/python_picnic_api2/client.py +++ b/src/python_picnic_api2/client.py @@ -15,6 +15,10 @@ GLOBAL_GATEWAY_URL = "https://gateway-prod.global.picnicinternational.com" DEFAULT_COUNTRY_CODE = "NL" DEFAULT_API_VERSION = "15" +_HEADERS = { + "x-picnic-agent": "30100;1.15.272-15295;", + "x-picnic-did": "3C417201548B2E3B", +} class PicnicAPI: @@ -47,14 +51,7 @@ def _get(self, path: str, add_picnic_headers=False): url = self._base_url + path # Make the request, add special picnic headers if needed - headers = ( - { - "x-picnic-agent": "30100;1.15.272-15295;", - "x-picnic-did": "3C417201548B2E3B", - } - if add_picnic_headers - else None - ) + headers = _HEADERS if add_picnic_headers else None response = self.session.get(url, headers=headers).json() if self._contains_auth_error(response): @@ -177,27 +174,21 @@ def print_categories(self, depth: int = 0): tree = "\n".join(_tree_generator(self.get_categories(depth=depth))) print(tree) - def get_product_from_gtin(self, etan: str, maxRedirects: int = 5): + def get_article_by_gtin(self, etan: str, maxRedirects: int = 5): + # Finds the article ID for a gtin/ean (barcode). - # Finds the product ID for a gtin/ean (barcode). - headers = ( - { - "x-picnic-agent": "30100;1.15.272-15295;", - "x-picnic-did": "3C417201548B2E3B", - } - ) url = "https://picnic.app/" + self._country_code.lower() + "/qr/gtin/" + etan while maxRedirects > 0: if url == "http://picnic.app/nl/link/store/storefront": # gtin unknown return None - r = self.session.get(url, headers=headers, allow_redirects=False) + r = self.session.get(url, headers=_HEADERS, allow_redirects=False) maxRedirects -= 1 if ";id=" in r.url: - # found the product id - return r.url.split(";id=",1)[1] + # found the article id + return self.get_article(r.url.split(";id=", 1)[1]) if "Location" not in r.headers: - # product id not found but also no futher redirect + # article id not found but also no futher redirect return None url = r.headers["Location"] return None From 7f47adbbd6d1d75e824244b4fbe0c7b929531605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Gro=C3=9F?= Date: Mon, 28 Apr 2025 19:29:15 +0000 Subject: [PATCH 09/17] Add unit test for ean search --- tests/test_client.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/test_client.py b/tests/test_client.py index 727129c..96a85ca 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -106,6 +106,14 @@ def test_search_encoding(self): headers=PICNIC_HEADERS, ) + def test_get_article_by_gtin(self): + self.client.get_article_by_gtin("123456789") + self.session_mock().get.assert_called_with( + "https://picnic.app/nl/qr/gtin/123456789", + headers=PICNIC_HEADERS, + allow_redirects=False, + ) + def test_get_cart(self): self.client.get_cart() self.session_mock().get.assert_called_with( From 3d8d3b1775faf1f899ee7fe8b8190f96310c9a26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Gro=C3=9F?= Date: Mon, 28 Apr 2025 20:17:37 +0000 Subject: [PATCH 10/17] Bump version to 1.3.0 --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index dff975b..211b508 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "python-picnic-api2" -version = "1.2.4" +version = "1.3.0" description = "" readme = "README.rst" license = {text = "Apache-2.0"} diff --git a/uv.lock b/uv.lock index 671d317..5aca350 100644 --- a/uv.lock +++ b/uv.lock @@ -197,7 +197,7 @@ wheels = [ [[package]] name = "python-picnic-api2" -version = "1.2.4" +version = "1.3.0" source = { editable = "." } dependencies = [ { name = "requests" }, From 301521e13a85729a90778a8a1820abcc4187dd7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Gro=C3=9F?= Date: Wed, 12 Mar 2025 16:55:51 +0000 Subject: [PATCH 11/17] Start working on new README file --- README.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..fc01ece --- /dev/null +++ b/README.md @@ -0,0 +1,39 @@ +# Python-Picnic-API + +Fork of the Unofficial Python wrapper for the [Picnic](https://picnic.app) API. While not all API methods have been implemented yet, you'll find most of what you need to build a working application are available. + +This library is not affiliated with Picnic and retrieves data from the endpoints of the mobile application. **Use at your own risk.** + +## Credits + +A big thanks to @MikeBrink for building the first versions of this library. + +@maartenpaul and @thijmen-j continously provided fixes that were then merged into this fork. + +## Getting started + +The easiest way to install is directly from pip: + +```bash +$ pip install python-picnic-api2 +``` + +Then create a new instance of `PicnicAPI` and login using your credentials: + +```python +from python_picnic_api import PicnicAPI + +picnic = PicnicAPI(username='username', password='password', country_code="NL") +``` + +The country_code parameter defaults to `NL`, but you have to change it if you live in a different country than the Netherlands (ISO 3166-1 Alpha-2). This obviously only works for countries that picnic services. + +## Searching for a product + +```python +picnic.search('coffee') +``` + +```python +[{'items': [{'id': 's1019822', 'name': 'Lavazza Caffè Crema e Aroma Bohnen', 'decorators': [], 'display_price': 1799, 'image_id': 'aecbf7d3b018025ec78daf5a1099b6842a860a2e3faeceec777c13d708ce442c', 'max_count': 99, 'unit_quantity': '1kg', 'sole_article_id': None}, ... ]}] +``` \ No newline at end of file From c0de56bdffa38e1f1fa581a190510f1e47d11c31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Gro=C3=9F?= Date: Mon, 28 Apr 2025 20:39:50 +0000 Subject: [PATCH 12/17] Add other API functions to README --- README.md | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fc01ece..e7e6d6a 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ picnic = PicnicAPI(username='username', password='password', country_code="NL") The country_code parameter defaults to `NL`, but you have to change it if you live in a different country than the Netherlands (ISO 3166-1 Alpha-2). This obviously only works for countries that picnic services. -## Searching for a product +## Searching for an article ```python picnic.search('coffee') @@ -36,4 +36,65 @@ picnic.search('coffee') ```python [{'items': [{'id': 's1019822', 'name': 'Lavazza Caffè Crema e Aroma Bohnen', 'decorators': [], 'display_price': 1799, 'image_id': 'aecbf7d3b018025ec78daf5a1099b6842a860a2e3faeceec777c13d708ce442c', 'max_count': 99, 'unit_quantity': '1kg', 'sole_article_id': None}, ... ]}] +``` + +## Get article by ID + +```python +picnic.get_article("s1019822") +``` +```python +{'name': 'Lavazza Caffè Crema e Aroma Bohnen', 'id': 's1019822'} +``` + +## Get article by GTIN (EAN) +```python +picnic.get_article_by_gtin("8000070025400") +``` +```python +{'name': 'Lavazza Caffè Crema e Aroma Bohnen', 'id': 's1019822'} +``` + +## Check cart + +```python +picnic.get_cart() +``` + +```python +{'type': 'ORDER', 'id': 'shopping_cart', 'items': [{'type': 'ORDER_LINE', 'id': '1470', 'items': [{'type': 'ORDER_ARTICLE', 'id': 's1019822', 'name': 'Lavazza Caffè Crema e Aroma Bohnen',... +``` + +## Manipulating your cart +All of these methods will return the shopping cart. + +```python +# Add product with ID "s1019822" 2x +picnic.add_product("s1019822", 2) + +# Remove product with ID "s1019822" 1x +picnic.remove_product("s1019822") + +# Clear your cart +picnic.clear_cart() +``` + +## See upcoming deliveries + +```python +picnic.get_current_deliveries() +``` + +```python +[{'delivery_id': 'XXYYZZ', 'creation_time': '2025-04-28T08:08:41.666+02:00', 'slot': {'slot_id': 'XXYYZZ', 'hub_id': '... +``` + +## See available delivery slots + +```python +picnic.get_delivery_slots() +``` + +```python +{'delivery_slots': [{'slot_id': 'XXYYZZ', 'hub_id': 'YYY', 'fc_id': 'FCX', 'window_start': '2025-04-29T17:15:00.000+02:00', 'window_end': '2025-04-29T19:15:00.000+02:00'... ``` \ No newline at end of file From 3816f4c0169ea6bde8096be52836267fad9c992d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Gro=C3=9F?= Date: Mon, 28 Apr 2025 20:43:38 +0000 Subject: [PATCH 13/17] Add warning about fast changes to API --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e7e6d6a..018026a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Python-Picnic-API +**This library is undergoing rapid changes as is the Picnic API itself. It is mainly intended for use within Home Assistant, but there are integration tests running regularly checking for failures in features not used bu the Home Assistant integration** + Fork of the Unofficial Python wrapper for the [Picnic](https://picnic.app) API. While not all API methods have been implemented yet, you'll find most of what you need to build a working application are available. This library is not affiliated with Picnic and retrieves data from the endpoints of the mobile application. **Use at your own risk.** From 844b8f946a00abd20b05a6158fd7558cdf9c034b Mon Sep 17 00:00:00 2001 From: TheNetworkGuy Date: Sat, 24 May 2025 15:12:59 +0200 Subject: [PATCH 14/17] Fixes tiny typo in the readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 018026a..3d117c5 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ $ pip install python-picnic-api2 Then create a new instance of `PicnicAPI` and login using your credentials: ```python -from python_picnic_api import PicnicAPI +from python_picnic_api2 import PicnicAPI picnic = PicnicAPI(username='username', password='password', country_code="NL") ``` @@ -99,4 +99,4 @@ picnic.get_delivery_slots() ```python {'delivery_slots': [{'slot_id': 'XXYYZZ', 'hub_id': 'YYY', 'fc_id': 'FCX', 'window_start': '2025-04-29T17:15:00.000+02:00', 'window_end': '2025-04-29T19:15:00.000+02:00'... -``` \ No newline at end of file +``` From 09c1620af2601ba9dfa0c908f84d7326177285d3 Mon Sep 17 00:00:00 2001 From: TheNetworkGuy Date: Sat, 24 May 2025 16:45:04 +0200 Subject: [PATCH 15/17] Fallback should there be no markup for a specific product --- src/python_picnic_api2/client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/python_picnic_api2/client.py b/src/python_picnic_api2/client.py index 8a02e72..9e37c21 100644 --- a/src/python_picnic_api2/client.py +++ b/src/python_picnic_api2/client.py @@ -114,7 +114,7 @@ def get_article(self, article_id: str, add_category_name=False): return None color_regex = re.compile(r"#\(#\d{6}\)") - producer = re.sub(color_regex, "", str(article_details[1]["markdown"])) + producer = re.sub(color_regex, "", str(article_details[1].get("markdown", ""))) article_name = re.sub(color_regex, "", str(article_details[0]["markdown"])) article = {"name": f"{producer} {article_name}", "id": article_id} From eba51c5e092c84492ca02b2247723d7d5af6bab6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Gro=C3=9F?= Date: Sun, 1 Jun 2025 10:34:05 +0000 Subject: [PATCH 16/17] Add test for get_article --- tests/test_client.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tests/test_client.py b/tests/test_client.py index 96a85ca..fdd4871 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -23,7 +23,8 @@ def json(self): return self.json_data def setUp(self) -> None: - self.session_patcher = patch("python_picnic_api2.client.PicnicAPISession") + self.session_patcher = patch( + "python_picnic_api2.client.PicnicAPISession") self.session_mock = self.session_patcher.start() self.client = PicnicAPI(username="test@test.nl", password="test") self.expected_base_url = DEFAULT_URL.format("nl", "15") @@ -106,6 +107,13 @@ def test_search_encoding(self): headers=PICNIC_HEADERS, ) + def test_get_article(self): + self.client.get_article("p3f2qa") + self.session_mock().get.assert_called_with( + "https://storefront-prod.nl.picnicinternational.com/api/15/pages/product-details-page-root?id=p3f2qa", + headers=PICNIC_HEADERS, + ) + def test_get_article_by_gtin(self): self.client.get_article_by_gtin("123456789") self.session_mock().get.assert_called_with( From c34bbf1011e0180564e44b010e0229ab350f94b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noah=20Gro=C3=9F?= Date: Sun, 1 Jun 2025 10:34:34 +0000 Subject: [PATCH 17/17] Bump verison to 1.3.1 --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 211b508..074f8ed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "python-picnic-api2" -version = "1.3.0" +version = "1.3.1" description = "" readme = "README.rst" license = {text = "Apache-2.0"} diff --git a/uv.lock b/uv.lock index 5aca350..f53a32e 100644 --- a/uv.lock +++ b/uv.lock @@ -197,7 +197,7 @@ wheels = [ [[package]] name = "python-picnic-api2" -version = "1.3.0" +version = "1.3.1" source = { editable = "." } dependencies = [ { name = "requests" },