diff --git a/core/medium_parser/core.py b/core/medium_parser/core.py index b736420..01301c4 100644 --- a/core/medium_parser/core.py +++ b/core/medium_parser/core.py @@ -6,23 +6,20 @@ import urllib.parse import jinja2 import tld from loguru import logger +from contextlib import suppress -from rl_string_helper import (RLStringHelper, parse_markups, - split_overlapping_ranges) +from rl_string_helper import RLStringHelper, parse_markups, split_overlapping_ranges from . import cache, jinja_env -from .exceptions import (InvalidMediumPostID, InvalidMediumPostURL, InvalidURL, - MediumParserException, MediumPostQueryError) +from .exceptions import InvalidMediumPostID, InvalidMediumPostURL, InvalidURL, MediumParserException, MediumPostQueryError from .medium_api import query_post_by_id from .models.html_result import HtmlResult from .time import convert_datetime_to_human_readable -from .utils import (get_medium_post_id_by_url, getting_percontage_of_match, - is_valid_medium_post_id_hexadecimal, is_valid_medium_url, - is_valid_url, sanitize_url) +from .utils import get_medium_post_id_by_url, getting_percontage_of_match, is_valid_medium_post_id_hexadecimal, is_valid_medium_url, is_valid_url, sanitize_url class MediumParser: - __slots__ = ('__post_id', 'post_data', 'jinja', 'timeout', 'host_address', 'auth_cookies') + __slots__ = ("__post_id", "post_data", "jinja", "timeout", "host_address", "auth_cookies") def __init__(self, post_id: str, timeout: int, host_address: str, auth_cookies: str = None): self.timeout = timeout @@ -32,14 +29,14 @@ class MediumParser: self.auth_cookies = auth_cookies @classmethod - async def from_url(cls, url: str, timeout: int, host_address: str, auth_cookies: str = None) -> 'MediumParser': + async def from_url(cls, url: str, timeout: int, host_address: str, auth_cookies: str = None) -> "MediumParser": sanitized_url = sanitize_url(url) if is_valid_url(url) and not await is_valid_medium_url(sanitized_url, timeout): - raise InvalidURL(f'Invalid medium URL: {sanitized_url}') + raise InvalidURL(f"Invalid Medium URL: {sanitized_url}") post_id = await get_medium_post_id_by_url(sanitized_url, timeout) if not post_id: - raise InvalidMediumPostURL(f'Could not find medium post ID for URL: {sanitized_url}') + raise InvalidMediumPostURL(f"Could not find Medium post ID for URL: {sanitized_url}") return cls(post_id, timeout, host_address, auth_cookies) @@ -50,7 +47,7 @@ class MediumParser: @post_id.setter def post_id(self, value): if not is_valid_medium_post_id_hexadecimal(value): - raise InvalidMediumPostID(f'Invalid medium post ID: {value}') + raise InvalidMediumPostID(f"Invalid medium post ID: {value}") self.__post_id = value @@ -67,22 +64,34 @@ class MediumParser: return True async def get_post_data_from_cache(self): - logger.debug("Using cache backend") - post_data = cache.pull(self.post_id) - if post_data: - logger.debug("post query was found on cache") - return post_data.json() - logger.debug(f"No data found in cache by {self.post_id}") + async def _get_from_cache(): + logger.debug("Using cache backend") + post_data = cache.pull(self.post_id) + if post_data: + logger.debug("post query was found on cache") + return post_data.json() + logger.debug(f"No data found in cache by {self.post_id}") + return None + + with suppress(Exception): + return await asyncio.wait_for(_get_from_cache(), timeout=self.timeout + 1) + return None async def get_post_data_from_api(self): - logger.debug("Cache backend disabled, using API") - try: - return await query_post_by_id(self.post_id, self.timeout, self.auth_cookies) - except Exception as ex: - logger.debug("Error while querying post by Medium API") - logger.exception(ex) - return None + async def _get_from_api(): + logger.debug("Using API backend") + try: + return await query_post_by_id(self.post_id, self.timeout, self.auth_cookies) + except Exception as ex: + logger.debug("Error while querying post by Medium API") + logger.exception(ex) + return None + + with suppress(Exception): + return await asyncio.wait_for(_get_from_api(), timeout=self.timeout + 1) + + return None async def query_get(self, use_cache: bool, force_cache: bool = False): cache_used = True @@ -123,13 +132,13 @@ class MediumParser: logger.error(f"Attempt {attempt + 1} failed with exception: {e}") finally: logger.info(f"Retrying in {2 ** attempt} seconds...") - await asyncio.sleep(2 ** attempt) + await asyncio.sleep(2**attempt) attempt += 1 else: if not reason: reason = "Unknown" - raise MediumPostQueryError(f'Could not query post by ID from API: {self.post_id}. Reason: {reason}') + raise MediumPostQueryError(f"Could not query post by ID from API: {self.post_id}. Reason: {reason}") if not is_cache_used: cache.push(self.post_id, post_data) @@ -238,9 +247,7 @@ class MediumParser: image_template = jinja_env.from_string( '