From 49b1d49d1c6544bbd92cfb0c8e975b65781486f8 Mon Sep 17 00:00:00 2001 From: mazen-r Date: Mon, 22 Dec 2025 22:48:14 +0200 Subject: [PATCH 1/3] fix msgpack bytes treated as mutable #36 --- scrapfly/api_response.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scrapfly/api_response.py b/scrapfly/api_response.py index 0038a53..3a3cf2c 100644 --- a/scrapfly/api_response.py +++ b/scrapfly/api_response.py @@ -43,6 +43,8 @@ def _date_parser(value): if isinstance(value, Dict): over = value.items() + elif isinstance(value, bytes): + return value else: over = enumerate(value) From feb170483e94df8c1c524a057bedd3153addb4c5 Mon Sep 17 00:00:00 2001 From: mazen-r Date: Tue, 23 Dec 2025 20:09:00 +0200 Subject: [PATCH 2/3] support screenshot api vision deficiency and fix error doc lookup --- .../screenshot_with_screenshot_api.py | 1 + scrapfly/api_response.py | 12 +++++++-- scrapfly/screenshot_config.py | 26 +++++++++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/examples/screenshot/screenshot_with_screenshot_api.py b/examples/screenshot/screenshot_with_screenshot_api.py index bd4bb21..723d137 100644 --- a/examples/screenshot/screenshot_with_screenshot_api.py +++ b/examples/screenshot/screenshot_with_screenshot_api.py @@ -17,6 +17,7 @@ rendering_wait=5000, # Delay in milliseconds to wait after the page was loaded wait_for_selector='div.products-wrap', # XPath or CSS selector to wait for auto_scroll=True, # Whether to automatically scroll down to the bottom of the page + # vision_deficiency=VisionDeficiency.DEUTERANOPIA, # Simulate vision deficiency ) ) diff --git a/scrapfly/api_response.py b/scrapfly/api_response.py index 3a3cf2c..2184675 100644 --- a/scrapfly/api_response.py +++ b/scrapfly/api_response.py @@ -228,14 +228,22 @@ def error_message(self): message = "<-- %s | %s - %s." % (self.response.status_code, self.error['code'], self.error['message']) if self.error['links']: - message += " Checkout the related doc: %s" % list(self.error['links'].values())[0] + links = self.error['links'] + if isinstance(links, dict): + message += " Checkout the related doc: %s" % list(links.values())[0] + elif isinstance(links, list): + message += " Checkout the related doc: %s" % ", ".join(links) return message message = "<-- %s | %s." % (self.response.status_code, self.result['message']) if self.result.get('links'): - message += " Checkout the related doc: %s" % ", ".join(self.result['links']) + links = self.result['links'] + if isinstance(links, dict): + message += " Checkout the related doc: %s" % list(links.values())[0] + elif isinstance(links, list): + message += " Checkout the related doc: %s" % ", ".join(links) return message diff --git a/scrapfly/screenshot_config.py b/scrapfly/screenshot_config.py index c542b8f..4623521 100644 --- a/scrapfly/screenshot_config.py +++ b/scrapfly/screenshot_config.py @@ -38,6 +38,24 @@ class Format(Enum): GIF = "gif" +class VisionDeficiency(Enum): + """ + Simulate vision deficiency for accessibility testing (WCAG compliance) + + Attributes: + DEUTERANOPIA: Red-green color blindness (green-blind), affects ~6% of males. + PROTANOPIA: Red-green color blindness (red-blind), affects ~2% of males + TRITANOPIA: Simulate color blindness. + ACHROMATOPSIA: Complete color blindness (monochromacy), affects ~0.003% + BLURREDVISION: Blurred/unfocused vision, affects ~2.2B globally + """ + DEUTERANOPIA = "deuteranopia" + PROTANOPIA = "protanopia" + TRITANOPIA = "tritanopia" + ACHROMATOPSIA = "achromatopsia" + BLURREDVISION = "blurredvision" + + class ScreenshotConfig(BaseApiConfig): url: str format: Optional[Format] = None @@ -72,6 +90,7 @@ def __init__( cache: Optional[bool] = None, cache_ttl: Optional[bool] = None, cache_clear: Optional[bool] = None, + vision_deficiency: Optional[VisionDeficiency] = None, webhook: Optional[str] = None, raise_on_upstream_error: bool = True ): @@ -92,6 +111,7 @@ def __init__( self.cache = cache self.cache_ttl = cache_ttl self.cache_clear = cache_clear + self.vision_deficiency = vision_deficiency self.webhook = webhook self.raise_on_upstream_error = raise_on_upstream_error @@ -147,6 +167,9 @@ def to_api_params(self, key:str) -> Dict: if self.cache_clear is not None: logging.warning('Params "cache_clear" is ignored. Works only if cache is enabled') + if self.vision_deficiency is not None: + params['vision_deficiency'] = self.vision_deficiency.value + if self.webhook is not None: params['webhook_name'] = self.webhook @@ -171,6 +194,7 @@ def to_dict(self) -> Dict: 'cache': self.cache, 'cache_ttl': self.cache_ttl, 'cache_clear': self.cache_clear, + 'vision_deficiency': self.vision_deficiency.value if self.vision_deficiency else None, 'webhook': self.webhook, 'raise_on_upstream_error': self.raise_on_upstream_error } @@ -198,6 +222,7 @@ def from_dict(screenshot_config_dict: Dict) -> 'ScreenshotConfig': cache = screenshot_config_dict.get('cache', None) cache_ttl = screenshot_config_dict.get('cache_ttl', None) cache_clear = screenshot_config_dict.get('cache_clear', None) + vision_deficiency = screenshot_config_dict.get('vision_deficiency', None) webhook = screenshot_config_dict.get('webhook', None) raise_on_upstream_error = screenshot_config_dict.get('raise_on_upstream_error', True) @@ -216,6 +241,7 @@ def from_dict(screenshot_config_dict: Dict) -> 'ScreenshotConfig': cache=cache, cache_ttl=cache_ttl, cache_clear=cache_clear, + vision_deficiency=vision_deficiency, webhook=webhook, raise_on_upstream_error=raise_on_upstream_error ) From fe95fa1e5620f44214261a66e734e0226b91e71e Mon Sep 17 00:00:00 2001 From: mazen-r Date: Tue, 23 Dec 2025 20:11:21 +0200 Subject: [PATCH 3/3] revert msgpack bytes handling commit --- scrapfly/api_response.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/scrapfly/api_response.py b/scrapfly/api_response.py index 2184675..77a9228 100644 --- a/scrapfly/api_response.py +++ b/scrapfly/api_response.py @@ -43,8 +43,6 @@ def _date_parser(value): if isinstance(value, Dict): over = value.items() - elif isinstance(value, bytes): - return value else: over = enumerate(value)