| 554 | return False |
| 555 | |
| 556 | def request(self, method, url, *, |
| 557 | params: Optional[dict] = None, |
| 558 | headers: Optional[dict] = None, |
| 559 | **kwargs |
| 560 | ) -> requests.Response: |
| 561 | |
| 562 | # read CachingSession-specific params |
| 563 | refresh = kwargs.pop('refresh_', False) |
| 564 | no_cache = kwargs.pop('no_cache_', False) |
| 565 | default_maxage = kwargs.pop('maxage_', None) |
| 566 | |
| 567 | if not self._cache_enabled or no_cache or method.lower() != 'get': |
| 568 | # completely bypass cache lookup and validation |
| 569 | return super().request(method, url, params=params, headers=headers, **kwargs) |
| 570 | |
| 571 | if default_maxage is None: |
| 572 | default_maxage = self._default_maxage |
| 573 | elif not isinstance(default_maxage, numbers.Real) or default_maxage < 0: |
| 574 | warnings.warn( |
| 575 | f"non-negative real value required for 'maxage_'; ignoring {default_maxage}", |
| 576 | UserWarning, stacklevel=2) |
| 577 | default_maxage = self._default_maxage |
| 578 | |
| 579 | key = (method, url, |
| 580 | self.params, params, |
| 581 | self.headers, headers) |
| 582 | |
| 583 | # note: metadata split from data for faster metadata-only updates |
| 584 | key_data = hashlib.sha256(repr(key).encode('utf8')).hexdigest() |
| 585 | key_meta = f"{key_data}:meta" |
| 586 | |
| 587 | def make_response(meta, content): |
| 588 | res = requests.Response() |
| 589 | res.status_code = 200 |
| 590 | res._content = content |
| 591 | res.headers['content-type'] = meta.get('content_type') |
| 592 | return res |
| 593 | |
| 594 | meta = self._store.get(key_meta) |
| 595 | # note: we need to force the file interface (with read=True) to avoid JSON |
| 596 | # deserialization. We read it immediately, so we can close the file. |
| 597 | if raw := self._store.get(key_data, read=True): |
| 598 | content = raw.read() |
| 599 | raw.close() |
| 600 | else: |
| 601 | content = None |
| 602 | |
| 603 | if not refresh and meta and content: |
| 604 | logger.debug("cache_read (meta): %r = %r", key_meta, meta) |
| 605 | logger.debug("cache_read (data): %r -> (%r bytes)", key_data, len(content)) |
| 606 | |
| 607 | # respect max-age from response cache-control |
| 608 | maxage = meta.get('maxage') |
| 609 | if maxage is None: |
| 610 | # but if cache-control was absent, client gets do decide |
| 611 | maxage = default_maxage |
| 612 | |
| 613 | if epochnow() - meta['created'] < maxage: |