# -*- coding: utf-8 -*- # pylint: disable=missing-module-docstring from http import HTTPStatus from urllib.parse import urlparse import requests from anaconda_navigator.utils.logs import logger class AdvertisementMixin: # pylint: disable=missing-class-docstring,too-few-public-methods def _is_valid_url(self, url): parse_result = urlparse(url) if not all((parse_result.scheme, parse_result.netloc, parse_result.path)): self.errors.append(f'{url} is not a valid URL') return False return True def _log_errors(self): for error in self.errors: logger.error(error) class AdvertisementsList(AdvertisementMixin): # pylint: disable=missing-class-docstring BANNER_TIMEOUT_MS = 60000 # pylint: disable=invalid-name def __init__(self, source_url): self.source_url = source_url self.advertisements = [] self.errors = [] self.load() self._log_errors() def load(self): """ Tries to load the data to be displayed in the advertisements. """ try: resp = requests.get(self.source_url) if resp.status_code == HTTPStatus.OK: for data in resp.json(): image_url = data.get('image_url') redirect_url = data.get('redirect_url') text = data.get('text') ad = Advertisement(image_url, redirect_url, text) # pylint: disable=invalid-name if ad.is_valid(): self.advertisements.append(ad) except requests.ConnectionError: self.errors.append(f'Tried to load advertisement data from {self.source_url}. URL is not reachable') except Exception as e: # pylint: disable=broad-except,invalid-name self.errors.append(f'Unexpected error while loading advertisement. Stacktrace: {str(e)}') def advertisements_carousel(self): # pylint: disable=missing-function-docstring start_pos = 0 adlen = len(self.advertisements) while start_pos < adlen: curr_pos = start_pos res = self.advertisements[start_pos] start_pos = (start_pos + 1) if start_pos + 1 < adlen else 0 yield curr_pos, res class Advertisement(AdvertisementMixin): # pylint: disable=too-few-public-methods """ Class for loading advertisements data, handling errors and validating data. """ def __init__(self, image_url, redirect_url, text): self.errors = [] self.image = None if self._is_valid_url(image_url): self.image = self._load_image(image_url) self.url = None if self._is_valid_url(redirect_url): self.url = redirect_url self.text = text self._log_errors() def is_valid(self): """ Checks if all needed data is present and correct. """ image_and_link = self.image and self.url text_and_link = self.text and self.url all_set = self.text and self.url and self.image return all_set or image_and_link or text_and_link def _load_image(self, image_url): """ Tries to load the image of an advertisement. :param str image_url: The url of the image to be downloaded. """ resp = requests.get(image_url) if resp.status_code == HTTPStatus.OK: return resp.content self.errors.append( f'Tried to load advertisement image from {image_url}. Data is not fetched with status {resp.status_code}', ) return None