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 1/7] 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 2/7] 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 3/7] 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 4/7] 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 5/7] 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 6/7] 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 7/7] 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" },