def test_stock_status_neq(): item1 = StockItem("EU", 42, "In Stock") item2 = StockItem("EU", 44, "Only 4 left") item3 = StockItem("EU", 40, "Out of Stock") status1 = StockStatus({item1, item2}) status2 = StockStatus({item1, item3}) assert not status1 == status2
def test_save_status_state(): item1 = StockItem("EU", 42, "In Stock") item2 = StockItem("EU", 44, "Only 4 left") status = StockStatus({item1, item2}, url="https://dummy.net") status.persist_state() status_from_statefile = StockStatus.from_statefile("https://dummy.net") assert status == status_from_statefile
def test_stock_status_to_pandas(): item1 = StockItem("EU", 42, "In Stock") item2 = StockItem("EU", 44, "Only 4 left") status = StockStatus({item1, item2}) stock = status.to_pandas() assert isinstance(stock, pd.DataFrame) cols = stock.columns assert "size_category" in cols assert "size" in cols assert "stock_status" in cols rows, _ = stock.shape assert rows == 2
def test_stock_comparison_df_to_none(): item1 = StockItem("EU", 42, "In Stock") item2 = StockItem("EU", 44, "Only 4 left") old_status = None new_status = StockStatus({item1, item2}) df = new_status.compare_to_older(old_status) cols = df.columns assert "size_category" in cols assert "size" in cols assert "stock_status_old" in cols assert "stock_status_new" in cols changed_row = df[df["size"] == 44] assert np.isnan(changed_row["stock_status_old"].values[0]) assert changed_row["stock_status_new"].values[0] == "Only 4 left"
def test_stock_comparison_df(): item1 = StockItem("EU", 42, "In Stock") item2_old = StockItem("EU", 44, "Only 4 left") item2_new = StockItem("EU", 44, "Out of Stock") old_status = StockStatus({item1, item2_old}) new_status = StockStatus({item1, item2_new}) df = new_status.compare_to_older(old_status) cols = df.columns assert "size_category" in cols assert "size" in cols assert "stock_status_old" in cols assert "stock_status_new" in cols changed_row = df[df["size"] == 44] assert changed_row["stock_status_old"].values[0] == "Only 4 left" assert changed_row["stock_status_new"].values[0] == "Out of Stock"
def notify_poll(self, url: str, items: StockStatus): to_update_str = " ".join(self.on_poll) table_html = "<pre>" + items.to_pandas().to_markdown( index="False") + "</pre>" message = f"{to_update_str}\nFetched new stock status for: {url}" self.bot.send_message(self.chat_id, message) self.bot.send_message(self.chat_id, table_html, parse_mode="html")
def notify_poll(self, url: str, items: StockStatus): to_update_str = " ".join(self.on_poll) print( to_update_str, "\n", f"Fetched new stock status for: {url}", "\n", items.to_pandas(), )
def notify_update(self, url: str, old_items: StockStatus, new_items: StockStatus): to_update_str = " ".join(self.on_update) comparison_df = new_items.compare_to_older(old_items) message = f"{to_update_str}\nStock status update for: {url}" table_html = "<pre>" + comparison_df.to_markdown( index="False") + "</pre>" self.bot.send_message(self.chat_id, message) self.bot.send_message(self.chat_id, table_html, parse_mode="html")
def __init__(self, url, parser_class, poll_frequency, notifier): self.url = url parser = parser_class(url) self.parser = parser self.poll_frequency_s = poll_frequency * 60 self.notifier = notifier try: persisted_state = StockStatus.from_statefile(url) self.state = persisted_state except FileNotFoundError: self.state = None
def load_stock(self) -> StockStatus: try: driver = self.driver_class() driver.get(self.url) size_select_elem = driver.find_element_by_class_name("select") sizes = size_select_elem.find_elements_by_tag_name("option") stock = {size.get_attribute("text") for size in sizes} stock = { StockItem.from_vivo_str(size) for size in stock if not size.startswith("Size") } finally: driver.close() return StockStatus(stock, url=self.url)
def notify_update(self, url: str, old_items: StockStatus, new_items: StockStatus): to_update_str = " ".join(self.on_update) comparison_df = new_items.compare_to_older(old_items) print(to_update_str, "\n", f"Stock status update for: {url}", "\n", comparison_df)