def test_print_categories(capsys): picnic = PicnicAPI() picnic.print_categories() captured = capsys.readouterr() assert isinstance(captured.out, str)
def test_login_failed(self): response = { "error": { "code": "AUTH_INVALID_CRED", "message": "Invalid credentials." } } self.session_mock().post.return_value = self.MockResponse( response, 200) client = PicnicAPI() with self.assertRaises(PicnicAuthError): client.login('test-user', 'test-password')
class PicnicSetupGrocy(): picnic = PicnicAPI(username=config.picnic_user, password=config.picnic_passwd, country_code="NL", store=False) grocy = GrocyAPI(config.picnic_img_size, config.picnic_img_baseurl) json_picnic_data = {} def importIntoGrocy(self, url: str, api_url: str, key: str): print("Starting importing: " + url) json_data = json.loads(requests.get(url).text) for obj in json_data[key]: print("Importing: " + obj["name"] + " into grocy database...") res = self.grocy.postToGrocy(api_url, obj) if not res.ok: print("failed importing: " + res.text) def setupQuantities(self): self.importIntoGrocy(config.picnic_quantity_list, "objects/quantity_units", "data") def setupUserfields(self): self.importIntoGrocy(config.picnic_userfields_list, "objects/userfields", "data") def setupStoreAndLocation(self): self.importIntoGrocy(config.picnic_stores_list, "objects/shopping_locations", "data") self.importIntoGrocy(config.picnic_location_list, "objects/locations", "data") def installAll(self): # make sure to have an empty grocy database. self.setupUserfields() self.setupStoreAndLocation() self.setupQuantities()
def search_items(picnic_api: PicnicAPI, term: str) -> List[Item]: result = picnic_api.search(term=term) items_dict = result[0]["items"] items = [ Item(**item) for item in items_dict if ("name" in item) and ("unit_quantity_sub" in item) ] return items
def test_login_credentials(self): self.session_mock().authenticated = False PicnicAPI(username='******', password='******') self.session_mock().post.assert_called_with( self.expected_base_url + '/user/login', json={ 'key': '*****@*****.**', 'secret': '098f6bcd4621d373cade4e832627b4f6', "client_id": 1 })
def cheapest( search_term: str = Argument(..., help="Search term for product."), n: int = Option(default=5, help="Max. number of cheapest findings to show."), username: str = Option(None, help="Username of Picnic account."), password: str = Option(None, help="Password of Picnic account."), country_code: str = Option(default="DE", help="Country code of shop."), ): # connect to picnic api if (not username) or (not password): print("loading credentials from config file...") username, password, country_code = credentials_from_file( path=CREDENTIALS_PATH) picnic = PicnicAPI(username=username, password=password, country_code=country_code) # search items, filter cheapest items = search_items(picnic_api=picnic, term=search_term) cheapest_items = filter_cheapest_items(items=items, max_n=n) # format results for item in cheapest_items: print(f"* {item.name}: {item.unit_quantity_sub}")
def test_get_delivery(): picnic = PicnicAPI() response = picnic.get_deliveries() deliveryId = response[0]["id"] response = picnic.get_delivery(deliveryId) assert isinstance(response, dict)
def test_get_deliveries(): picnic = PicnicAPI() response_1 = picnic.get_deliveries() response_2 = picnic.get_deliveries(summary=True) assert isinstance(response_1, list) assert isinstance(response_2, list)
def test_get_delivery_slots(): picnic = PicnicAPI() response = picnic.get_delivery_slots() assert isinstance(response, dict)
class PicNic(): picnic_user = config.picnic_user picnic_passwd = config.picnic_passwd picnic_image_size = config.picnic_img_size picnic_img_baseurl = config.picnic_img_baseurl picnic_numofelementsimport = config.picnic_max_import_products picnic_ean_codes_url = config.picnic_product_ean_list quantities = dict() grocy_items = [] picnic = PicnicAPI(username=picnic_user, password=picnic_passwd, country_code="NL", store=False) grocy = GrocyAPI(picnic_image_size, picnic_img_baseurl) json_picnic_data = {} picnic_store_id = "" picnic_last_delivery_id = "" home_location_id = "" def __init__(self): # download all json ean products from file json_data = json.loads(requests.get(self.picnic_ean_codes_url).text) self.json_picnic_data = json_data["data"] self.getAllGrocyProducts() # first load all existing grocy products. self.getQuantityUnits() # import all grocy quantities. self.getPicnicStoreData( ) # get store ID and delivery ID with name Picnic self.getHomeLocationID() # get location ID with name Home # print(self.getProductInformation(10465898)) def getEANFromPicnicID(self, picnic_id: str): for json_item in self.json_picnic_data: if str(json_item["picnic_id"]) == picnic_id: return str(json_item["ean"]) return "" def getHomeLocationID(self): json_data = self.grocy.getFromGrocy("objects/locations") found_location = [x for x in json_data if x["name"] == "Home"] if len(found_location) > 0: self.home_location_id = found_location[0]["id"] def getPicnicStoreData(self): json_data = self.grocy.getFromGrocy("objects/shopping_locations") found_store = [x for x in json_data if x["name"] == "Picnic"] if len(found_store) > 0: self.picnic_store_id = found_store[0]["id"] self.picnic_last_delivery_id = found_store[0]["userfields"][ "lastdeliveryid"] def setLastDeliveryID(self, delivery_id: str): self.grocy.addUserFieldToStore( str(self.picnic_store_id), "{\"lastdeliveryid\":\"" + delivery_id + "\"}") def addPicnicIDToProduct(self, product_id: str, picnic_id: str): self.grocy.addUserFieldToProduct(str(product_id), "{\"picnic\":\"" + picnic_id + "\"}") def addPicNicProductToGrocy(self, name: str, qu_id: str, picnic_id: str, imgId: str, price: str): postData = {} postData["name"] = name postData["qu_id_purchase"] = qu_id postData["qu_id_stock"] = qu_id postData["qu_factor_purchase_to_stock"] = 1.0 postData["shopping_location_id"] = self.picnic_store_id postData["location_id"] = self.home_location_id postData["barcode"] = self.getEANFromPicnicID(picnic_id) # disable tenminste houdtbaar tot postData["default_best_before_days"] = config.disable_tht result = self.grocy.postToGrocy("objects/products", postData) if result.ok: json_result = json.loads(result.text) grocy_product_id = json_result["created_object_id"] print("Added picnic product to grocy: " + grocy_product_id + ", picnic_id: " + picnic_id) self.addPicnicIDToProduct(grocy_product_id, picnic_id) print("Uploading picnic image to grocy...") self.grocy.changePictureFileNameProduct( grocy_product_id, self.grocy.addPictureToProduct(imgId)) return grocy_product_id else: print("Failed to add picnic product to grocy: " + result.text) return 0 def getProductInformation(self, productID: str): path = "/product/" + str(productID) # , just a test. return self.picnic._get(path) def importLastPicnicDelivery(self): last_delivery_index = -1 order_data = self.picnic.get_deliveries( )[0]["orders"][last_delivery_index]["creation_time"] delivery_date = self.picnic.get_deliveries( )[0]["delivery_time"]["start"] delivery_id = self.picnic.get_deliveries()[0]["delivery_id"] if self.picnic_last_delivery_id == delivery_id: print("Failed: order already imported, exit script...") return self.setLastDeliveryID(delivery_id) print("Setting last delivery ID: " + json.dumps(delivery_id)) # last order of picnic for picnic_item in self.picnic.get_deliveries()[0]["orders"][ last_delivery_index]["items"][:self. picnic_numofelementsimport]: # picnic data: name = picnic_item["items"][0]["name"] id = picnic_item["items"][0]["id"] image_ids = picnic_item["items"][0]["image_ids"][0] # used in stock data price = (picnic_item["items"][0]["price"] / 100) unit_quantity = picnic_item["items"][0]["unit_quantity"] converted_quantity = self.fillQuantity(unit_quantity) sort_of_quantity = converted_quantity[1] how_much = converted_quantity[0] # grocy_data: grocy_id_existing_product = self.getPicnicProductInGrocy(id) if grocy_id_existing_product != 0: # print("picnic item already in grocy..." + price) print("Increasing stock: " + how_much + " with id: " + sort_of_quantity) self.setInStock(grocy_id_existing_product, how_much, price, order_data) else: new_grocy_id = self.addPicNicProductToGrocy( name, sort_of_quantity, id, image_ids, price) if new_grocy_id != 0: self.setInStock(new_grocy_id, how_much, price, order_data) # todo increase stock after adding product. def fillQuantity(self, quantity_text: str): replaced_text = quantity_text.replace(",", ".") temp = re.compile("([\d.]*\d+) ([a-zA-Z]+)") res = temp.match(replaced_text).groups() if res[1] == "x": temp = re.compile("([\d.]*\d+) x ([\d.]*\d+) ([a-zA-Z]+)") res = temp.match(replaced_text).groups() calculatie = int(res[0]) * int(res[1]) new = [calculatie, res[2]] return [ str(new[0]), str(self.matchPicnicQuantityByGrocyQuantity(new[1])) ] else: # returns HOW_MUCH, WHAT_KIND_OF return [ str(res[0]), str(self.matchPicnicQuantityByGrocyQuantity(res[1])) ] def matchPicnicQuantityByGrocyQuantity(self, picnicQuantity: str): #print("picnicquanitity: " + picnicQuantity) found_quantity = ([ self.quantities[key] for key in self.quantities if picnicQuantity in key.lower() ]) if len(found_quantity) > 0: return found_quantity[0] else: return 0 # return self.quantities[picnicQuantity]["id"] # for quantity in self.quantities: # if picnicQuantity == quantity["name"): # return quantity["id"] def getQuantityUnits(self): json_data = self.grocy.getFromGrocy('objects/quantity_units') for quantity in json_data: self.quantities[quantity["name"]] = quantity["id"] # print(self.quantities) def setInStock(self, grocy_id: str, stock: str, price: str, order_date): post_data = {} post_data["amount"] = str(stock) post_data["price"] = str(price) post_data["purchased_date"] = str(order_date) # order_date print("grocy_id: " + grocy_id) result = self.grocy.postToGrocy('stock/products/' + grocy_id + '/add', post_data) if result.ok: print("setInStock: succes") else: print("Failed to add stock: " + result.text) def getPicnicProductInGrocy(self, picnic_id: str): for grocy_item in self.grocy_items: if grocy_item.picnic_id == picnic_id: return grocy_item.grocy_id return 0 def getAllGrocyProducts(self): json_data = self.grocy.getFromGrocy('objects/products') for product in json_data: grocy_product = GrocyPicnicProduct(product["userfields"]["picnic"], product["id"], product["name"], product["picture_file_name"], product["tare_weight"], product["qu_id_stock"]) self.grocy_items.append(grocy_product)
from python_picnic_api import PicnicAPI from dotenv import load_dotenv import os load_dotenv() username = os.getenv("USERNAME") password = os.getenv("PASSWORD") country_code = os.getenv("COUNTRY_CODE") picnic = PicnicAPI(username, password, country_code=country_code) def _get_amount(cart: dict, product_id: str): items = cart["items"][0]["items"] product = next((item for item in items if item["id"] == product_id), None) return product["decorators"][0]["quantity"] def test_get_user(): response = picnic.get_user() assert isinstance(response, dict) assert "contact_email" in response.keys() assert response["contact_email"] == username def test_search(): response = picnic.search("koffie") assert isinstance(response, list) assert isinstance(response[0], dict) assert "id" in response[0].keys()
def test_login_auth_token(self): self.session_mock().authenticated = True PicnicAPI(username='******', password='******', auth_token='a3fwo7f3h78kf3was7h8f3ahf3ah78f3') self.session_mock().login.assert_not_called()
def setUp(self) -> None: self.session_patcher = patch( "python_picnic_api.client.PicnicAPISession") self.session_mock = self.session_patcher.start() self.client = PicnicAPI(username="******", password="******") self.expected_base_url = DEFAULT_URL.format("nl", "15")
class TestClient(unittest.TestCase): class MockResponse: def __init__(self, json_data, status_code): self.json_data = json_data self.status_code = status_code def json(self): return self.json_data def setUp(self) -> None: self.session_patcher = patch( "python_picnic_api.client.PicnicAPISession") self.session_mock = self.session_patcher.start() self.client = PicnicAPI(username="******", password="******") self.expected_base_url = DEFAULT_URL.format("nl", "15") def tearDown(self) -> None: self.session_patcher.stop() def test_login_credentials(self): self.session_mock().authenticated = False PicnicAPI(username='******', password='******') self.session_mock().post.assert_called_with( self.expected_base_url + '/user/login', json={ 'key': '*****@*****.**', 'secret': '098f6bcd4621d373cade4e832627b4f6', "client_id": 1 }) def test_login_auth_token(self): self.session_mock().authenticated = True PicnicAPI(username='******', password='******', auth_token='a3fwo7f3h78kf3was7h8f3ahf3ah78f3') self.session_mock().login.assert_not_called() def test_login_failed(self): response = { "error": { "code": "AUTH_INVALID_CRED", "message": "Invalid credentials." } } self.session_mock().post.return_value = self.MockResponse( response, 200) client = PicnicAPI() with self.assertRaises(PicnicAuthError): client.login('test-user', 'test-password') def test_get_user(self): response = { "user_id": "594-241-3623", "firstname": "Firstname", "lastname": "Lastname", "address": { "house_number": 25, "house_number_ext": "b", "postcode": "1234 AB", "street": "Dorpsstraat", "city": "Het dorp", }, "phone": "+31123456798", "contact_email": "*****@*****.**", "total_deliveries": 25, "completed_deliveries": 20, } self.session_mock().get.return_value = self.MockResponse(response, 200) user = self.client.get_user() self.session_mock().get.assert_called_with(self.expected_base_url + "/user", headers=None) self.assertDictEqual(user, response) def test_search(self): self.client.search("test-product") self.session_mock().get.assert_called_with( self.expected_base_url + "/search?search_term=test-product", headers=None) def test_get_lists(self): self.client.get_lists() self.session_mock().get.assert_called_with(self.expected_base_url + "/lists", headers=None) def test_get_sublist(self): self.client.get_sublist(list_id="promotion", sublist_id="12345") self.session_mock().get.assert_called_with( self.expected_base_url + "/lists/promotion?sublist=12345", headers=None) def test_get_list_by_id(self): self.client.get_lists("abc") self.session_mock().get.assert_called_with(self.expected_base_url + "/lists/abc", headers=None) def test_get_cart(self): self.client.get_cart() self.session_mock().get.assert_called_with(self.expected_base_url + "/cart", headers=None) def test_add_product(self): self.client.add_product("p3f2qa") self.session_mock().post.assert_called_with( self.expected_base_url + "/cart/add_product", json={ "product_id": "p3f2qa", "count": 1 }, ) def test_add_multiple_products(self): self.client.add_product("gs4puhf3a", count=5) self.session_mock().post.assert_called_with( self.expected_base_url + "/cart/add_product", json={ "product_id": "gs4puhf3a", "count": 5 }, ) def test_remove_product(self): self.client.remove_product("gs4puhf3a", count=5) self.session_mock().post.assert_called_with( self.expected_base_url + "/cart/remove_product", json={ "product_id": "gs4puhf3a", "count": 5 }, ) def test_clear_cart(self): self.client.clear_cart() self.session_mock().post.assert_called_with(self.expected_base_url + "/cart/clear", json=None) def test_get_delivery_slots(self): self.client.get_delivery_slots() self.session_mock().get.assert_called_with(self.expected_base_url + "/cart/delivery_slots", headers=None) def test_get_delivery(self): self.client.get_delivery("3fpawshusz3") self.session_mock().get.assert_called_with(self.expected_base_url + "/deliveries/3fpawshusz3", headers=None) def test_get_delivery_scenario(self): self.client.get_delivery_scenario("3fpawshusz3") self.session_mock().get.assert_called_with( self.expected_base_url + "/deliveries/3fpawshusz3/scenario", headers=PICNIC_HEADERS, ) def test_get_delivery_position(self): self.client.get_delivery_position("3fpawshusz3") self.session_mock().get.assert_called_with( self.expected_base_url + "/deliveries/3fpawshusz3/position", headers=PICNIC_HEADERS, ) def test_get_deliveries(self): self.client.get_deliveries() self.session_mock().post.assert_called_with(self.expected_base_url + "/deliveries", json=[]) def test_get_deliveries_summary(self): self.client.get_deliveries(summary=True) self.session_mock().post.assert_called_with(self.expected_base_url + "/deliveries/summary", json=[]) def test_get_current_deliveries(self): self.client.get_current_deliveries() self.session_mock().post.assert_called_with(self.expected_base_url + "/deliveries", json=["CURRENT"]) def test_get_categories(self): self.session_mock().get.return_value = self.MockResponse( { "type": "MY_STORE", "catalog": [ { "type": "CATEGORY", "id": "purchases", "name": "Besteld" }, { "type": "CATEGORY", "id": "promotions", "name": "Acties" }, ], "user": {}, }, 200, ) categories = self.client.get_categories() self.session_mock().get.assert_called_with(self.expected_base_url + "/my_store?depth=0", headers=None) self.assertDictEqual(categories[0], { "type": "CATEGORY", "id": "purchases", "name": "Besteld" }) def test_get_auth_exception(self): self.session_mock().get.return_value = self.MockResponse( {"error": { "code": "AUTH_ERROR" }}, 400) with self.assertRaises(PicnicAuthError): self.client.get_user() def test_post_auth_exception(self): self.session_mock().post.return_value = self.MockResponse( {"error": { "code": "AUTH_ERROR" }}, 400) with self.assertRaises(PicnicAuthError): self.client.clear_cart()
def test_get_current_deliveries(): picnic = PicnicAPI() response = picnic.get_current_deliveries() assert isinstance(response, list)
def test_get_categories(): picnic = PicnicAPI() response = picnic.get_categories() assert isinstance(response, list)
def test_get_lists(): picnic = PicnicAPI() response_1 = picnic.get_lists() response_2 = picnic.get_lists("21725") assert isinstance(response_1, list) assert isinstance(response_2, list)
def test_search(): picnic = PicnicAPI() response = picnic.search("koffie") assert isinstance(response, list)
def test_get_user(): picnic = PicnicAPI() response = picnic.get_user() assert isinstance(response, dict)
def authenticate(username, password, country_code) -> tuple[str, dict]: """Test if we can authenticate with the Picnic API.""" picnic = PicnicAPI(username, password, country_code) return picnic.session.auth_token, picnic.get_user()
def test_remove_product(): picnic = PicnicAPI() response = picnic.remove_product("10407428") assert isinstance(response, dict)
def create_picnic_client(entry: ConfigEntry): """Create an instance of the PicnicAPI client.""" return PicnicAPI( auth_token=entry.data.get(CONF_ACCESS_TOKEN), country_code=entry.data.get(CONF_COUNTRY_CODE), )
def test_clear_cart(): picnic = PicnicAPI() response = picnic.clear_cart() assert isinstance(response, dict)